package ext_tools; import static org.openstreetmap.josm.tools.I18n.tr; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.openstreetmap.josm.command.AddCommand; import org.openstreetmap.josm.command.ChangeCommand; import org.openstreetmap.josm.command.ChangeNodesCommand; import org.openstreetmap.josm.command.Command; import org.openstreetmap.josm.data.osm.*; final class DataSetToCmd { /** the source dataset where primitives are merged from */ private final DataSet sourceDataSet; /** * A map of all primitives that got replaced with other primitives. Key is * the PrimitiveId in their dataset, the value is the PrimitiveId in my * dataset */ private final Map<PrimitiveId, OsmPrimitive> mergedMap = new HashMap<>(); private final LinkedList<Command> cmds = new LinkedList<>(); /** * constructor */ public DataSetToCmd(DataSet sourceDataSet) { this.sourceDataSet = sourceDataSet; merge(); } /** * Merges a primitive <code>other</code> of type * <P> * onto my primitives. * * @param <P> * the type of the other primitive * @param source * the other primitive */ private void mergePrimitive(OsmPrimitive source) { OsmPrimitive target = null; switch (source.getType()) { case NODE: target = new Node(); break; case WAY: target = new Way(); break; case RELATION: target = new Relation(); break; default: throw new AssertionError(); } target.mergeFrom(source); mergedMap.put(source.getPrimitiveId(), target); cmds.add(new AddCommand(target)); } private OsmPrimitive getMergeTarget(OsmPrimitive mergeSource) throws IllegalStateException { OsmPrimitive target = mergedMap.get(mergeSource.getPrimitiveId()); if (target == null) return null; return target; } /** * Postprocess the dataset and fix all merged references to point to the * actual data. */ public void fixReferences() { for (Way w : sourceDataSet.getWays()) { mergeNodeList(w); } for (Relation r : sourceDataSet.getRelations()) { mergeRelationMembers(r); } } /** * Merges the node list of a source way onto its target way. * * @param source * the source way * @throws IllegalStateException * thrown if no target way can be found for the source way * @throws IllegalStateException * thrown if there isn't a target node for one of the nodes in * the source way * */ private void mergeNodeList(Way source) throws IllegalStateException { Way target = (Way) getMergeTarget(source); if (target == null) throw new IllegalStateException(tr( "Missing merge target for way with id {0}", source.getUniqueId())); if (target.getDataSet() != null) throw new IllegalStateException(tr( "Missing merge target for way with id {0}", source.getUniqueId())); List<Node> newNodes = new ArrayList<>(source.getNodesCount()); for (Node sourceNode : source.getNodes()) { Node targetNode = (Node) getMergeTarget(sourceNode); if (targetNode == null) throw new IllegalStateException(tr( "Missing merge target for node with id {0}", sourceNode .getUniqueId())); if (targetNode.getDataSet() != null) throw new IllegalStateException(tr( "Missing merge target for way with id {0}", source.getUniqueId())); newNodes.add(targetNode); } cmds.add(new ChangeNodesCommand(target, newNodes)); } /** * Merges the relation members of a source relation onto the corresponding * target relation. * * @param source * the source relation * @throws IllegalStateException * thrown if there is no corresponding target relation * @throws IllegalStateException * thrown if there isn't a corresponding target object for one * of the relation members in source */ private void mergeRelationMembers(Relation source) throws IllegalStateException { Relation target = (Relation) getMergeTarget(source); if (target == null) throw new IllegalStateException( tr("Missing merge target for relation with id {0}", source .getUniqueId())); if (target.getDataSet() != null) throw new IllegalStateException( tr("Missing merge target for relation with id {0}", source .getUniqueId())); LinkedList<RelationMember> newMembers = new LinkedList<>(); for (RelationMember sourceMember : source.getMembers()) { OsmPrimitive targetMember = getMergeTarget(sourceMember.getMember()); if (targetMember == null) throw new IllegalStateException(tr( "Missing merge target of type {0} with id {1}", sourceMember .getType(), sourceMember.getUniqueId())); if (targetMember.getDataSet() != null) throw new IllegalStateException(tr( "Missing merge target of type {0} with id {1}", sourceMember .getType(), sourceMember.getUniqueId())); newMembers.add(new RelationMember(sourceMember.getRole(), targetMember)); } Relation newRelation = new Relation(target); newRelation.setMembers(newMembers); cmds.add(new ChangeCommand(target, newRelation)); } private void merge() { for (Node node : sourceDataSet.getNodes()) { mergePrimitive(node); } for (Way way : sourceDataSet.getWays()) { mergePrimitive(way); } for (Relation relation : sourceDataSet.getRelations()) { mergePrimitive(relation); } fixReferences(); } public LinkedList<Command> getCommandList() { return cmds; } }