Ticket #3475: backRefVisitor.diff

File backRefVisitor.diff, 11.1 KB (added by Petr Dlouhý <petr.dlouhy@…>, 3 years ago)
  • src/org/openstreetmap/josm/actions/search/SearchCompiler.java

     
    3232    private boolean regexSearch = false; 
    3333    private String  rxErrorMsg = marktr("The regex \"{0}\" had a parse error at offset {1}, full error:\n\n{2}"); 
    3434    private PushbackTokenizer tokenizer; 
     35    private static CollectBackReferencesVisitor childBackRefs; 
    3536 
    3637    public SearchCompiler(boolean caseSensitive, boolean regexSearch, PushbackTokenizer tokenizer) { 
    3738        this.caseSensitive = caseSensitive; 
    3839        this.regexSearch = regexSearch; 
    3940        this.tokenizer = tokenizer; 
     41        childBackRefs = new CollectBackReferencesVisitor(Main.main.getCurrentDataSet()); 
    4042    } 
    4143 
    4244    abstract public static class Match { 
     
    480482            } 
    481483 
    482484            boolean isChild = false; 
    483             CollectBackReferencesVisitor backRefs = new CollectBackReferencesVisitor(Main.main.getCurrentDataSet()); 
    484             osm.visit(backRefs); 
    485             for (OsmPrimitive p : backRefs.data) { 
     485            childBackRefs.initialize(); 
     486            osm.visit(childBackRefs); 
     487            for (OsmPrimitive p : childBackRefs.getData()) { 
    486488                isChild |= parent.match(p); 
    487489            } 
    488490            return isChild; 
  • src/org/openstreetmap/josm/actions/search/SearchAction.java

     
    181181               searchText = "(" + s.text + ")" + (((Filter)s).applyForChildren ? ("| child (" + s.text + ")"): ""); 
    182182               searchText = (((Filter)s).inverted ? "-" : "") + "(" +  searchText + ")"; 
    183183            } 
    184             System.out.println(searchText); 
     184            /*System.out.println(searchText);*/ 
    185185            SearchCompiler.Match matcher = SearchCompiler.compile(searchText, s.caseSensitive, s.regexSearch); 
    186186            foundMatches = 0; 
    187187            for (OsmPrimitive osm : Main.main.getCurrentDataSet().allNonDeletedCompletePrimitives()) { 
  • src/org/openstreetmap/josm/actions/CreateCircleAction.java

     
    171171            if (a1 < 999) { 
    172172                // if it is, delete it 
    173173                CollectBackReferencesVisitor refs = new CollectBackReferencesVisitor(getCurrentDataSet()); 
     174                refs.initialize(); 
    174175                refs.visit(n1); 
    175                 if (refs.data.isEmpty() || ((refs.data.size() == 1) && (refs.data.contains(existingWay)))) { 
     176                if (refs.getData().isEmpty() || ((refs.getData().size() == 1) && (refs.getData().contains(existingWay)))) { 
    176177                    cmds.add(new DeleteCommand(n1)); 
    177178                } 
    178179 
  • src/org/openstreetmap/josm/data/osm/visitor/CollectBackReferencesVisitor.java

     
    33 
    44import java.util.Collection; 
    55import java.util.HashSet; 
     6import java.util.HashMap; 
     7import java.util.Map; 
    68 
    79import org.openstreetmap.josm.data.osm.DataSet; 
    810import org.openstreetmap.josm.data.osm.Node; 
     
    1618 * 
    1719 * Deleted objects are not collected. 
    1820 * 
    19  * @author imi 
     21 * @author imi, Petr DlouhÜ 
    2022 */ 
    2123public class CollectBackReferencesVisitor extends AbstractVisitor { 
    2224 
    2325    private final DataSet ds; 
    2426    private final boolean indirectRefs; 
    2527 
    26     /** 
    27      * The result list of primitives stored here. 
    28      */ 
    29     public final Collection<OsmPrimitive> data = new HashSet<OsmPrimitive>(); 
     28    private Collection<OsmPrimitive> data = new HashSet<OsmPrimitive>(); 
     29    private Map<OsmPrimitive, Collection<OsmPrimitive>> lookupTable = new HashMap<OsmPrimitive, Collection<OsmPrimitive>>(); 
    3030 
    3131 
    3232    /** 
    3333     * Construct a back reference counter. 
     34     * has time complexity O(n) - so it is appropriate not to call it in cycle 
    3435     * @param ds The dataset to operate on. 
    3536     */ 
    3637    public CollectBackReferencesVisitor(DataSet ds) { 
    3738        this.ds = ds; 
    3839        this.indirectRefs = true; 
     40        makeLookupTable(); 
    3941    } 
    4042 
     43    /** 
     44     * Construct a back reference counter. 
     45     * has time complexity O(n) - so it is appropriate not to call it in cycle 
     46     * @param ds The dataset to operate on. 
     47     * @param indirectRefs Make also indirect references? 
     48     */ 
    4149    public CollectBackReferencesVisitor(DataSet ds, boolean indirectRefs) { 
    4250        this.ds = ds; 
    4351        this.indirectRefs = indirectRefs; 
     52        makeLookupTable(); 
    4453    } 
    45  
    46     public void visit(Node n) { 
     54     
     55    private void makeLookupTable(){ 
    4756        for (Way w : ds.ways) { 
    48             if (w.isDeleted() || w.incomplete) { 
    49                 continue; 
    50             } 
    51             for (Node n2 : w.getNodes()) { 
    52                 if (n == n2) { 
    53                     data.add(w); 
    54                     if (indirectRefs) { 
    55                         visit(w); 
    56                     } 
    57                 } 
    58             } 
     57           for (Node n : w.getNodes()) { 
     58              if(!lookupTable.containsKey(n)) lookupTable.put(n, new HashSet<OsmPrimitive>()); 
     59              lookupTable.get(n).add(w); 
     60           } 
    5961        } 
    60         checkRelationMembership(n); 
     62        for (Relation r : ds.relations) { 
     63           for (RelationMember m : r.getMembers()) { 
     64              OsmPrimitive o = m.getMember(); 
     65              if(!lookupTable.containsKey(o)) lookupTable.put(o, new HashSet<OsmPrimitive>()); 
     66              lookupTable.get(o).add(r); 
     67           } 
     68        } 
    6169    } 
    6270 
     71    /** 
     72     * Get the result collection 
     73     */ 
     74    public Collection<OsmPrimitive> getData(){ 
     75       return data; 
     76    } 
     77 
     78    /** 
     79     * Initialize data before associated visit calls  
     80     */ 
     81    public void initialize(){ 
     82       data = new HashSet<OsmPrimitive>(); 
     83    } 
     84 
     85    public void visit(OsmPrimitive o) { 
     86       if(lookupTable.containsKey(o)){ 
     87          Collection<OsmPrimitive> c = lookupTable.get(o); 
     88          Collection<OsmPrimitive> oldData = new HashSet<OsmPrimitive>(data); 
     89          data.addAll(c); 
     90          if(indirectRefs) 
     91             for(OsmPrimitive oo : c) 
     92                if(!oldData.contains(oo)) 
     93                   visit(oo); 
     94       } 
     95    } 
     96     
     97    public void visit(Node n) { 
     98       visit((OsmPrimitive)n); 
     99    } 
     100 
    63101    public void visit(Way w) { 
    64         checkRelationMembership(w); 
     102       visit((OsmPrimitive)w); 
    65103    } 
    66104 
    67105    public void visit(Relation r) { 
    68         checkRelationMembership(r); 
     106       visit((OsmPrimitive)r); 
    69107    } 
    70  
    71     private void checkRelationMembership(OsmPrimitive p) { 
    72         // FIXME - this might be a candidate for optimisation 
    73         // if OSM primitives are made to hold a list of back 
    74         // references. 
    75         for (Relation r : ds.relations) { 
    76             if (r.incomplete || r.isDeleted()) { 
    77                 continue; 
    78             } 
    79             for (RelationMember m : r.getMembers()) { 
    80                 if (m.getMember() == p) { 
    81                     if (!data.contains(r)) { 
    82                         data.add(r); 
    83                         if (indirectRefs) { 
    84                             // move up the tree (there might be relations 
    85                             // referring to this relation) 
    86                             checkRelationMembership(r); 
    87                         } 
    88                     } 
    89                     break; 
    90                 } 
    91             } 
    92         } 
    93     } 
    94108} 
  • src/org/openstreetmap/josm/command/DeleteCommand.java

     
    163163    public static Command deleteWithReferences(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection, boolean simulate) { 
    164164        CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(layer.data); 
    165165        for (OsmPrimitive osm : selection) { 
     166            v.initialize(); 
    166167            osm.visit(v); 
    167168        } 
    168         v.data.addAll(selection); 
    169         if (v.data.isEmpty()) 
     169        v.getData().addAll(selection); 
     170        if (v.getData().isEmpty()) 
    170171            return null; 
    171         if (!checkAndConfirmOutlyingDeletes(layer,v.data) && !simulate) 
     172        if (!checkAndConfirmOutlyingDeletes(layer,v.getData()) && !simulate) 
    172173            return null; 
    173         return new DeleteCommand(layer,v.data); 
     174        return new DeleteCommand(layer,v.getData()); 
    174175    } 
    175176 
    176177    public static Command deleteWithReferences(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection) { 
     
    238239     */ 
    239240    protected static Collection<Node> computeNodesToDelete(OsmDataLayer layer, Collection<OsmPrimitive> primitivesToDelete) { 
    240241        Collection<Node> nodesToDelete = new HashSet<Node>(); 
     242        CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(layer.data, false); 
    241243        for (OsmPrimitive osm : primitivesToDelete) { 
    242244            if (! (osm instanceof Way) ) { 
    243245                continue; 
     
    246248                if (n.isTagged()) { 
    247249                    continue; 
    248250                } 
    249                 CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(layer.data, false); 
     251                v.initialize(); 
    250252                n.visit(v); 
    251                 v.data.removeAll(primitivesToDelete); 
    252                 if (v.data.isEmpty()) { 
     253                v.getData().removeAll(primitivesToDelete); 
     254                if (v.getData().isEmpty()) { 
    253255                    nodesToDelete.add(n); 
    254256                } 
    255257            } 
     
    296298        if (!simulate && !checkAndConfirmOutlyingDeletes(layer,primitivesToDelete)) 
    297299            return null; 
    298300 
     301        CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(layer.data, false); 
    299302        for (OsmPrimitive osm : primitivesToDelete) { 
    300             CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(layer.data, false); 
     303            v.initialize(); 
    301304            osm.visit(v); 
    302             for (OsmPrimitive ref : v.data) { 
     305            for (OsmPrimitive ref : v.getData()) { 
    303306                if (primitivesToDelete.contains(ref)) { 
    304307                    continue; 
    305308                } 
     
    327330            if (wnew.getNodesCount() < 2) { 
    328331                primitivesToDelete.add(w); 
    329332 
    330                 CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(layer.data, false); 
     333                v.initialize(); 
    331334                w.visit(v); 
    332                 for (OsmPrimitive ref : v.data) { 
     335                for (OsmPrimitive ref : v.getData()) { 
    333336                    if (primitivesToDelete.contains(ref)) { 
    334337                        continue; 
    335338                    }