Changeset 2168 in josm for trunk/src/org/openstreetmap/josm/data
- Timestamp:
- 2009-09-20T11:46:08+02:00 (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/data/APIDataSet.java
r2039 r2168 2 2 package org.openstreetmap.josm.data; 3 3 4 import java.util.ArrayList; 5 import java.util.Collection; 6 import java.util.Collections; 7 import java.util.Comparator; 8 import java.util.HashMap; 9 import java.util.HashSet; 4 10 import java.util.LinkedList; 5 11 import java.util.List; 12 import java.util.Set; 13 import java.util.Stack; 14 import java.util.logging.Logger; 6 15 7 16 import org.openstreetmap.josm.data.osm.DataSet; 17 import org.openstreetmap.josm.data.osm.Node; 8 18 import org.openstreetmap.josm.data.osm.OsmPrimitive; 19 import org.openstreetmap.josm.data.osm.Relation; 20 import org.openstreetmap.josm.data.osm.RelationMember; 21 import org.openstreetmap.josm.data.osm.Way; 22 23 import org.openstreetmap.josm.actions.upload.CyclicUploadDependencyException; 9 24 10 25 /** … … 13 28 * The collection is derived from the modified primitives of an {@see DataSet}. 14 29 * 15 * FIXME: use to optimize the upload order before uploading, see various tickets in trac16 30 * 17 31 */ … … 113 127 return ret; 114 128 } 129 130 /** 131 * Adjusts the upload order for new relations. Child relations are uploaded first, 132 * parent relations second. 133 * 134 * This method detects cyclic dependencies in new relation. Relations with cyclic 135 * dependencies can't be uploaded. 136 * 137 * @throws CyclicUploadDependencyException thrown, if a cyclic dependency is detected 138 */ 139 public void adjustRelationUploadOrder() throws CyclicUploadDependencyException{ 140 LinkedList<OsmPrimitive> newToAdd = new LinkedList<OsmPrimitive>(); 141 newToAdd.addAll(OsmPrimitive.getFilteredList(toAdd, Node.class)); 142 newToAdd.addAll(OsmPrimitive.getFilteredList(toAdd, Way.class)); 143 144 List<Relation> relationsToAdd = OsmPrimitive.getFilteredList(toAdd, Relation.class); 145 List<Relation> noProblemRelations = filterRelationsNotReferringToNewRelations(relationsToAdd); 146 newToAdd.addAll(noProblemRelations); 147 relationsToAdd.removeAll(noProblemRelations); 148 149 RelationUploadDependencyGraph graph = new RelationUploadDependencyGraph(relationsToAdd); 150 newToAdd.addAll(graph.computeUploadOrder()); 151 toAdd = newToAdd; 152 } 153 154 /** 155 * Replies the subset of relations in <code>relations</code> which are not referring to any 156 * new relation 157 * 158 * @param relations a list of relations 159 * @return the subset of relations in <code>relations</code> which are not referring to any 160 * new relation 161 */ 162 protected List<Relation> filterRelationsNotReferringToNewRelations(Collection<Relation> relations) { 163 List<Relation> ret = new LinkedList<Relation>(); 164 for (Relation relation: relations) { 165 boolean refersToNewRelation = false; 166 for (RelationMember m : relation.getMembers()) { 167 if (m.isRelation() && m.getMember().getId() <= 0) { 168 refersToNewRelation = true; 169 break; 170 } 171 } 172 if (!refersToNewRelation) { 173 ret.add(relation); 174 } 175 } 176 return ret; 177 } 178 179 /** 180 * Utility class to sort a collection of of new relations with their dependencies 181 * topologically. 182 * 183 */ 184 private class RelationUploadDependencyGraph { 185 private final Logger logger = Logger.getLogger(RelationUploadDependencyGraph.class.getName()); 186 private HashMap<Relation, Set<Relation>> children; 187 private Collection<Relation> relations; 188 private Set<Relation> visited; 189 private List<Relation> uploadOrder; 190 191 public RelationUploadDependencyGraph() { 192 this.children = new HashMap<Relation, Set<Relation>>(); 193 this.visited = new HashSet<Relation>(); 194 } 195 196 public RelationUploadDependencyGraph(Collection<Relation> relations) { 197 this(); 198 build(relations); 199 } 200 201 public void build(Collection<Relation> relations) { 202 this.relations = new HashSet<Relation>(); 203 for(Relation relation: relations) { 204 if (relation.getId() > 0 ) { 205 continue; 206 } 207 this.relations.add(relation); 208 for (RelationMember m: relation.getMembers()) { 209 if (m.isRelation() && m.getMember().getId() == 0) { 210 addDependency(relation, (Relation)m.getMember()); 211 } 212 } 213 } 214 } 215 216 public Set<Relation> getChildren(Relation relation) { 217 Set<Relation> p = children.get(relation); 218 if (p == null) { 219 p = new HashSet<Relation>(); 220 children.put(relation, p); 221 } 222 return p; 223 } 224 225 public void addDependency(Relation relation, Relation child) { 226 getChildren(relation).add(child); 227 } 228 229 protected void visit(Stack<Relation> path, Relation current) throws CyclicUploadDependencyException{ 230 if (path.contains(current)) { 231 path.push(current); 232 throw new CyclicUploadDependencyException(path); 233 } 234 if (!visited.contains(current)) { 235 path.push(current); 236 visited.add(current); 237 for (Relation dependent : getChildren(current)) { 238 visit(path,dependent); 239 } 240 uploadOrder.add(current); 241 path.pop(); 242 } 243 } 244 245 public List<Relation> computeUploadOrder() throws CyclicUploadDependencyException { 246 visited = new HashSet<Relation>(); 247 uploadOrder = new LinkedList<Relation>(); 248 Stack<Relation> path = new Stack<Relation>(); 249 for (Relation relation: relations) { 250 visit(path, relation); 251 } 252 ArrayList<Relation> ret = new ArrayList<Relation>(relations); 253 Collections.sort( 254 ret, 255 new Comparator<Relation>() { 256 public int compare(Relation o1, Relation o2) { 257 return new Integer(uploadOrder.indexOf(o1)).compareTo(uploadOrder.indexOf(o2)); 258 } 259 } 260 ); 261 return ret; 262 } 263 } 115 264 }
Note:
See TracChangeset
for help on using the changeset viewer.