Logo Search packages:      
Sourcecode: josm version File versions  Download package

OsmWriter.java

// License: GPL. Copyright 2007 by Immanuel Scholz and others
package org.openstreetmap.josm.io;

import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map.Entry;

import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.data.osm.DataSet;
import org.openstreetmap.josm.data.osm.DataSource;
import org.openstreetmap.josm.data.osm.Relation;
import org.openstreetmap.josm.data.osm.RelationMember;
import org.openstreetmap.josm.data.osm.Node;
import org.openstreetmap.josm.data.osm.OsmPrimitive;
import org.openstreetmap.josm.data.osm.Way;
import org.openstreetmap.josm.data.osm.visitor.Visitor;

/**
 * Save the dataset into a stream as osm intern xml format. This is not using any
 * xml library for storing.
 * @author imi
 */
00023 public class OsmWriter extends XmlWriter implements Visitor {

      /**
       * The counter for new created objects. Starting at -1 and goes down.
       */
00028       private long newIdCounter = -1;
      /**
       * All newly created ids and their primitive that uses it. This is a back reference
       * map to allow references to use the correnct primitives.
       */
00033       private HashMap<OsmPrimitive, Long> usedNewIds = new HashMap<OsmPrimitive, Long>();

      private final boolean osmConform;

      public abstract static class Osm implements OsmWriterInterface {
            public void header(PrintWriter out) {
                  out.print("<osm version='");
                  out.print(Main.pref.get("osm-server.version", "0.5"));
                  out.println("' generator='JOSM'>");
            }
            public void footer(PrintWriter out) {
                  out.println("</osm>");
            }
      }
      
      // simple helper to write the object's class to the out stream
      private Visitor typeWriteVisitor = new Visitor() {
            public void visit(Node n) { out.print("node"); }
            public void visit(Way w) { out.print("way"); }
            public void visit(Relation e) { out.print("relation"); }
      };
      
      /**
       * An output writer for function output that writes everything of the given dataset into
       * the xml
       */
00059       public static final class All extends Osm {
            private final DataSet ds;
            private final boolean osmConform;

            /**
             * Construct an writer function
             * @param osmConform <code>true</code>, if the xml should be 100% osm conform. In this
             *          case, not all information can be retrieved later (as example, modified state
             *          is lost and id's remain 0 instead of decrementing from -1)
             */
00069             public All(DataSet ds, boolean osmConform) {
                  this.ds = ds;
                  this.osmConform = osmConform;
            }

            public void write(PrintWriter out) {
                  Visitor writer = new OsmWriter(out, osmConform);
                  for (Node n : ds.nodes)
                        if (shouldWrite(n))
                              writer.visit(n);
                  for (Way w : ds.ways)
                        if (shouldWrite(w))
                              writer.visit(w);
                  for (Relation e : ds.relations)
                        if (shouldWrite(e))
                              writer.visit(e);
        }

            private boolean shouldWrite(OsmPrimitive osm) {
              return osm.id != 0 || !osm.deleted;
        }

            @Override public void header(PrintWriter out) {
              super.header(out);
                  for (DataSource s : ds.dataSources) {
                        out.print("  <bound box='"+
                                    s.bounds.min.lat()+","+
                                    s.bounds.min.lon()+","+
                                    s.bounds.max.lat()+","+
                                    s.bounds.max.lon()+"' ");
                        out.println("origin='"+XmlWriter.encode(s.origin)+"' />");
                  }
        }
      }

      /**
       * An output writer for functino output that writes only one specific primitive into
       * the xml
       */
00108       public static final class Single extends Osm {
            private final OsmPrimitive osm;
            private final boolean osmConform;

            public Single(OsmPrimitive osm, boolean osmConform) {
                  this.osm = osm;
                  this.osmConform = osmConform;
            }

            public void write(PrintWriter out) {
                  osm.visit(new OsmWriter(out, osmConform));
        }
      }

      private OsmWriter(PrintWriter out, boolean osmConform) {
            super(out);
            this.osmConform = osmConform;
      }

      public void visit(Node n) {
            if (n.incomplete) return;
            addCommon(n, "node");
            out.print(" lat='"+n.coor.lat()+"' lon='"+n.coor.lon()+"'");
            addTags(n, "node", true);
      }

      public void visit(Way w) {
            if (w.incomplete) return;
            addCommon(w, "way");
            out.println(">");
            for (Node n : w.nodes)
                  out.println("    <nd ref='"+getUsedId(n)+"' />");
            addTags(w, "way", false);
      }

      public void visit(Relation e) {
            if (e.incomplete) return;
            addCommon(e, "relation");
            out.println(">");
            for (RelationMember em : e.members) {
                  out.print("    <member type='");
                  em.member.visit(typeWriteVisitor);
                  out.println("' ref='"+getUsedId(em.member)+"' role='" + 
                        XmlWriter.encode(em.role) + "' />");
            }
            addTags(e, "relation", false);
      }
      

      /**
       * Return the id for the given osm primitive (may access the usedId map)
       */
00160       private long getUsedId(OsmPrimitive osm) {
            if (osm.id != 0)
                  return osm.id;
            if (usedNewIds.containsKey(osm))
                  return usedNewIds.get(osm);
            usedNewIds.put(osm, newIdCounter);
            return osmConform ? 0 : newIdCounter--;
      }


      private void addTags(OsmPrimitive osm, String tagname, boolean tagOpen) {
            if (osm.keys != null) {
                  if (tagOpen)
                        out.println(">");
                  for (Entry<String, String> e : osm.keys.entrySet())
                        out.println("    <tag k='"+ XmlWriter.encode(e.getKey()) +
                                    "' v='"+XmlWriter.encode(e.getValue())+ "' />");
                  out.println("  </" + tagname + ">");
            } else if (tagOpen)
                  out.println(" />");
            else
                  out.println("  </" + tagname + ">");
      }

      /**
       * Add the common part as the form of the tag as well as the XML attributes
       * id, action, user, and visible.
       */
00188       private void addCommon(OsmPrimitive osm, String tagname) {
            out.print("  <"+tagname+" id='"+getUsedId(osm)+"'");
            if (!osmConform) {
                  String action = null;
                  if (osm.deleted)
                        action = "delete";
                  else if (osm.modified)
                        action = "modify";
                  if (action != null)
                        out.print(" action='"+action+"'");
            }
            if (osm.timestamp != null) {
                  out.print(" timestamp='"+osm.timestamp+"'");
            }
            // user and visible added with 0.4 API
            if (osm.user != null) {
                  out.print(" user='"+XmlWriter.encode(osm.user.name)+"'");
            }
            out.print(" visible='"+osm.visible+"'");
            
      }
}

Generated by  Doxygen 1.6.0   Back to index