[2512] | 1 | // License: GPL. For details, see LICENSE file.
|
---|
| 2 | package org.openstreetmap.josm.data.osm.visitor;
|
---|
| 3 |
|
---|
| 4 | import java.util.ArrayList;
|
---|
| 5 | import java.util.HashMap;
|
---|
| 6 | import java.util.List;
|
---|
[6317] | 7 | import java.util.Map;
|
---|
[2512] | 8 |
|
---|
| 9 | import org.openstreetmap.josm.data.osm.DataSet;
|
---|
| 10 | import org.openstreetmap.josm.data.osm.Node;
|
---|
[3265] | 11 | import org.openstreetmap.josm.data.osm.NodeData;
|
---|
[2512] | 12 | import org.openstreetmap.josm.data.osm.OsmPrimitive;
|
---|
[2978] | 13 | import org.openstreetmap.josm.data.osm.PrimitiveData;
|
---|
[2512] | 14 | import org.openstreetmap.josm.data.osm.Relation;
|
---|
[2978] | 15 | import org.openstreetmap.josm.data.osm.RelationData;
|
---|
[2512] | 16 | import org.openstreetmap.josm.data.osm.RelationMember;
|
---|
[2978] | 17 | import org.openstreetmap.josm.data.osm.RelationMemberData;
|
---|
[2512] | 18 | import org.openstreetmap.josm.data.osm.Way;
|
---|
[2978] | 19 | import org.openstreetmap.josm.data.osm.WayData;
|
---|
[2845] | 20 | import org.openstreetmap.josm.tools.CheckParameterUtil;
|
---|
[2512] | 21 |
|
---|
| 22 | /**
|
---|
[5266] | 23 | * MergeSourceBuildingVisitor helps to build the "hull" of a collection of {@link OsmPrimitive}s
|
---|
[2512] | 24 | * which shall be merged into another layer. The "hull" is slightly bigger than the original
|
---|
| 25 | * collection. It includes, for instance the nodes of a way in the original collection even though
|
---|
| 26 | * these nodes might not be present explicitly in the original collection. The "hull" also includes
|
---|
[5266] | 27 | * incomplete {@link OsmPrimitive}s which are referred to by relations in the original collection. And
|
---|
| 28 | * it turns {@link OsmPrimitive} referred to by {@link Relation}s in the original collection into
|
---|
| 29 | * incomplete {@link OsmPrimitive}s in the "hull", if they are not themselves present in the
|
---|
[2512] | 30 | * original collection.
|
---|
| 31 | *
|
---|
| 32 | */
|
---|
| 33 | public class MergeSourceBuildingVisitor extends AbstractVisitor {
|
---|
[9067] | 34 | private final DataSet selectionBase;
|
---|
| 35 | private final DataSet hull;
|
---|
| 36 | private final Map<OsmPrimitive, PrimitiveData> mappedPrimitives;
|
---|
[2512] | 37 |
|
---|
| 38 | /**
|
---|
| 39 | * Creates the visitor. The visitor starts to build the "hull" from
|
---|
| 40 | * the currently selected primitives in the dataset <code>selectionBase</code>,
|
---|
[5266] | 41 | * i.e. from {@link DataSet#getSelected()}.
|
---|
[2512] | 42 | *
|
---|
| 43 | * @param selectionBase the dataset. Must not be null.
|
---|
[8291] | 44 | * @throws IllegalArgumentException if selectionBase is null
|
---|
[2512] | 45 | */
|
---|
[8291] | 46 | public MergeSourceBuildingVisitor(DataSet selectionBase) {
|
---|
[2845] | 47 | CheckParameterUtil.ensureParameterNotNull(selectionBase, "selectionBase");
|
---|
[2512] | 48 | this.selectionBase = selectionBase;
|
---|
| 49 | this.hull = new DataSet();
|
---|
[7005] | 50 | this.mappedPrimitives = new HashMap<>();
|
---|
[2512] | 51 | }
|
---|
| 52 |
|
---|
[2620] | 53 | protected boolean isInSelectionBase(OsmPrimitive primitive) {
|
---|
[5360] | 54 | return selectionBase.getAllSelected().contains(primitive);
|
---|
[2620] | 55 | }
|
---|
| 56 |
|
---|
| 57 | protected boolean isAlreadyRemembered(OsmPrimitive primitive) {
|
---|
| 58 | return mappedPrimitives.keySet().contains(primitive);
|
---|
| 59 | }
|
---|
| 60 |
|
---|
[2512] | 61 | /**
|
---|
| 62 | * Remebers a node in the "hull"
|
---|
| 63 | *
|
---|
| 64 | * @param n the node
|
---|
| 65 | */
|
---|
| 66 | protected void rememberNode(Node n) {
|
---|
| 67 | if (isAlreadyRemembered(n))
|
---|
| 68 | return;
|
---|
[2978] | 69 | mappedPrimitives.put(n, n.save());
|
---|
[2512] | 70 | }
|
---|
| 71 |
|
---|
| 72 | /**
|
---|
| 73 | * remembers a way in the hull
|
---|
| 74 | *
|
---|
| 75 | * @param w the way
|
---|
| 76 | */
|
---|
| 77 | protected void rememberWay(Way w) {
|
---|
| 78 | if (isAlreadyRemembered(w))
|
---|
| 79 | return;
|
---|
[2978] | 80 | WayData clone = w.save();
|
---|
[7005] | 81 | List<Long> newNodes = new ArrayList<>(w.getNodesCount());
|
---|
[2512] | 82 | for (Node n: w.getNodes()) {
|
---|
[2978] | 83 | newNodes.add(mappedPrimitives.get(n).getUniqueId());
|
---|
[2512] | 84 | }
|
---|
| 85 | clone.setNodes(newNodes);
|
---|
| 86 | mappedPrimitives.put(w, clone);
|
---|
| 87 | }
|
---|
| 88 |
|
---|
| 89 | /**
|
---|
| 90 | * Remembers a relation in the hull
|
---|
| 91 | *
|
---|
| 92 | * @param r the relation
|
---|
| 93 | */
|
---|
| 94 | protected void rememberRelation(Relation r) {
|
---|
[2978] | 95 | RelationData clone;
|
---|
[2620] | 96 | if (isAlreadyRemembered(r)) {
|
---|
[8510] | 97 | clone = (RelationData) mappedPrimitives.get(r);
|
---|
[2512] | 98 | } else {
|
---|
[2978] | 99 | clone = r.save();
|
---|
| 100 | mappedPrimitives.put(r, clone);
|
---|
[2512] | 101 | }
|
---|
| 102 |
|
---|
[7005] | 103 | List<RelationMemberData> newMembers = new ArrayList<>();
|
---|
[2512] | 104 | for (RelationMember member: r.getMembers()) {
|
---|
| 105 | newMembers.add(
|
---|
[2978] | 106 | new RelationMemberData(member.getRole(), mappedPrimitives.get(member.getMember())));
|
---|
[2512] | 107 |
|
---|
| 108 | }
|
---|
| 109 | clone.setMembers(newMembers);
|
---|
| 110 | }
|
---|
| 111 |
|
---|
| 112 | protected void rememberRelationPartial(Relation r) {
|
---|
| 113 | if (isAlreadyRemembered(r))
|
---|
| 114 | return;
|
---|
[2978] | 115 | RelationData clone = r.save();
|
---|
| 116 | clone.getMembers().clear();
|
---|
[2512] | 117 | mappedPrimitives.put(r, clone);
|
---|
| 118 | }
|
---|
| 119 |
|
---|
| 120 | protected void rememberIncomplete(OsmPrimitive primitive) {
|
---|
| 121 | if (isAlreadyRemembered(primitive))
|
---|
| 122 | return;
|
---|
[2978] | 123 | PrimitiveData clone = primitive.save();
|
---|
| 124 | clone.setIncomplete(true);
|
---|
[2512] | 125 | mappedPrimitives.put(primitive, clone);
|
---|
| 126 | }
|
---|
| 127 |
|
---|
[6084] | 128 | @Override
|
---|
[2512] | 129 | public void visit(Node n) {
|
---|
| 130 | rememberNode(n);
|
---|
| 131 | }
|
---|
| 132 |
|
---|
[6084] | 133 | @Override
|
---|
[2512] | 134 | public void visit(Way w) {
|
---|
| 135 | // remember all nodes this way refers to ...
|
---|
| 136 | //
|
---|
| 137 | for (Node n: w.getNodes()) {
|
---|
[6010] | 138 | n.accept(this);
|
---|
[2512] | 139 | }
|
---|
| 140 | // ... and the way itself
|
---|
| 141 | rememberWay(w);
|
---|
| 142 | }
|
---|
| 143 |
|
---|
[6084] | 144 | @Override
|
---|
[2512] | 145 | public void visit(Relation r) {
|
---|
| 146 | // first, remember all primitives members refer to (only if necessary, see
|
---|
| 147 | // below)
|
---|
| 148 | //
|
---|
| 149 | rememberRelationPartial(r);
|
---|
| 150 | for (RelationMember member: r.getMembers()) {
|
---|
| 151 | if (isAlreadyRemembered(member.getMember())) {
|
---|
| 152 | // referred primitive already remembered
|
---|
| 153 | //
|
---|
| 154 | continue;
|
---|
| 155 | }
|
---|
[2978] | 156 | if (isInSelectionBase(member.getMember()) || member.getMember().isNew()) {
|
---|
[6010] | 157 | member.getMember().accept(this);
|
---|
[2978] | 158 | } else {
|
---|
| 159 | rememberIncomplete(member.getMember());
|
---|
[2512] | 160 | }
|
---|
| 161 | }
|
---|
| 162 | rememberRelation(r);
|
---|
| 163 | }
|
---|
| 164 |
|
---|
| 165 | protected void buildHull() {
|
---|
[2978] | 166 | // Create all primitives first
|
---|
| 167 | for (PrimitiveData primitive: mappedPrimitives.values()) {
|
---|
[3440] | 168 | OsmPrimitive newPrimitive = hull.getPrimitiveById(primitive);
|
---|
| 169 | boolean created = newPrimitive == null;
|
---|
| 170 | if (created) {
|
---|
| 171 | newPrimitive = primitive.getType().newInstance(primitive.getUniqueId(), true);
|
---|
[2978] | 172 | }
|
---|
[3440] | 173 | if (newPrimitive instanceof Node && !primitive.isIncomplete()) {
|
---|
| 174 | newPrimitive.load(primitive);
|
---|
| 175 | }
|
---|
| 176 | if (created) {
|
---|
| 177 | hull.addPrimitive(newPrimitive);
|
---|
| 178 | }
|
---|
[2978] | 179 | }
|
---|
[3265] | 180 | // Then ways and relations
|
---|
| 181 | for (PrimitiveData primitive : mappedPrimitives.values()) {
|
---|
[3440] | 182 | if (!(primitive instanceof NodeData) && !primitive.isIncomplete()) {
|
---|
| 183 | hull.getPrimitiveById(primitive).load(primitive);
|
---|
[3265] | 184 | }
|
---|
| 185 | }
|
---|
[2512] | 186 | }
|
---|
| 187 |
|
---|
| 188 | public DataSet build() {
|
---|
[5360] | 189 | for (OsmPrimitive primitive: selectionBase.getAllSelected()) {
|
---|
[6010] | 190 | primitive.accept(this);
|
---|
[2512] | 191 | }
|
---|
| 192 | buildHull();
|
---|
| 193 | return hull;
|
---|
| 194 | }
|
---|
| 195 | }
|
---|