Ticket #3475: backRefVisitor.diff

File backRefVisitor.diff, 11.1 KB (added by PetrDlouhy, 16 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                    }