// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.plugins.trustosm.io;
import java.io.BufferedWriter;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.openstreetmap.josm.data.osm.Node;
import org.openstreetmap.josm.data.osm.OsmPrimitive;
import org.openstreetmap.josm.io.XmlWriter;
import org.openstreetmap.josm.plugins.trustosm.data.TrustNode;
import org.openstreetmap.josm.plugins.trustosm.data.TrustOsmPrimitive;
import org.openstreetmap.josm.plugins.trustosm.data.TrustRelation;
import org.openstreetmap.josm.plugins.trustosm.data.TrustSignatures;
import org.openstreetmap.josm.plugins.trustosm.data.TrustWay;
public class SigWriter extends XmlWriter {
private String indent = "";
public SigWriter(PrintWriter out) {
super(out);
}
public SigWriter(OutputStream out) throws UnsupportedEncodingException {
super(new PrintWriter(new BufferedWriter(new OutputStreamWriter(out, "UTF-8"))));
}
public void write(Collection<TrustOsmPrimitive> items) {
writeHeader();
indent = " ";
writeItems(items);
writeFooter();
out.flush();
}
private void writeDTD() {
out.println("<!DOCTYPE trustXML [");
out.println(" <!ELEMENT trustXML (trustnode|trustway|trustrelation)*>");
out.println(" <!ATTLIST trustXML version CDATA #IMPLIED creator CDATA #IMPLIED >");
out.println(" <!ELEMENT trustnode (tags?,node?)>");
out.println(" <!ELEMENT trustway (tags?,segmentlist?)>");
out.println(" <!ELEMENT trustrelation (tags?,memberlist?)>");
out.println(" <!ATTLIST trustnode osmid CDATA #IMPLIED >");
out.println(" <!ATTLIST trustway osmid CDATA #IMPLIED >");
out.println(" <!ATTLIST trustrelation osmid CDATA #IMPLIED >");
out.println(" <!ELEMENT tags (key)+>");
out.println(" <!ELEMENT key (openpgp)+>");
out.println(" <!ATTLIST key k CDATA #IMPLIED >");
out.println(" <!ELEMENT node (openpgp)>");
// out.println(" <!ATTLIST node id CDATA #REQUIRED >");
out.println(" <!ELEMENT segmentlist (segment)*>");
out.println(" <!ELEMENT segment (openpgp)+>");
out.println(" <!ELEMENT memberlist (member)*>");
out.println(" <!ELEMENT member (openpgp)+>");
out.println(" <!ELEMENT openpgp (#PCDATA)*>");
out.println("]>");
}
private void writeHeader() {
out.println("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>");
writeDTD();
out.println("<trustXML version=\"0.1\" creator=\"JOSM Signature export\">");
}
private void writeFooter() {
out.println("</trustXML>");
}
private void writeSigs(TrustSignatures tsigs) {
for (String plain : tsigs.getAllPlainTexts()) {
simpleTag("openpgp", tsigs.getArmoredFulltextSignatureAll(plain));
}
}
private void writeTags(TrustOsmPrimitive trust) {
Map<String, TrustSignatures> tagsigs = trust.getTagSigs();
Set<String> signedKeys = tagsigs.keySet();
if (signedKeys.isEmpty()) return;
openln("tags");
for (String key : signedKeys) {
openAtt("key", "k=\""+key+"\"");
writeSigs(tagsigs.get(key));
closeln("key");
}
closeln("tags");
}
private void writeNode(TrustNode tn) {
TrustSignatures tsigs = tn.getNodeSigs();
if (tsigs == null) return;
openln("node");
writeSigs(tsigs);
closeln("node");
}
private void writeSegments(TrustWay tw) {
Map<List<Node>, TrustSignatures> segmentSig = tw.getSegmentSigs();
Set<List<Node>> signedSegments = segmentSig.keySet();
if (signedSegments.isEmpty()) return;
openln("segmentlist");
for (List<Node> segment : signedSegments) {
openln("segment");
writeSigs(segmentSig.get(segment));
closeln("segment");
}
closeln("segmentlist");
}
private void writeMembers(TrustRelation tr) {
Map<String, TrustSignatures> memberSig = tr.getMemberSigs();
Set<String> signedMembers = memberSig.keySet();
if (signedMembers.isEmpty()) return;
openln("memberlist");
for (String member : signedMembers) {
openln("member");
writeSigs(memberSig.get(member));
closeln("member");
}
closeln("memberlist");
}
private void writeItems(Collection<TrustOsmPrimitive> items) {
for (TrustOsmPrimitive trust : items) {
OsmPrimitive osm = trust.getOsmPrimitive();
if (trust instanceof TrustNode) {
TrustNode tn = (TrustNode) trust;
openAtt("trustnode", "osmid=\""+String.valueOf(osm.getUniqueId())+"\"");
writeTags(tn);
writeNode(tn);
closeln("trustnode");
} else if (trust instanceof TrustWay) {
TrustWay tw = (TrustWay) trust;
openAtt("trustway", "osmid=\""+String.valueOf(osm.getUniqueId())+"\"");
writeTags(tw);
writeSegments(tw);
closeln("trustway");
} else if (trust instanceof TrustRelation) {
TrustRelation tr = (TrustRelation) trust;
openAtt("trustrelation", "osmid=\""+String.valueOf(osm.getUniqueId())+"\"");
writeTags(tr);
writeMembers(tr);
closeln("trustrelation");
}
// openAtt("trustitem", "osmid=\""+String.valueOf(osm.getUniqueId())+"\" type=\""+osm.getType().getAPIName()+"\"");
}
}
private void openln(String tag) {
open(tag);
out.println();
}
private void open(String tag) {
out.print(indent + "<" + tag + ">");
indent += " ";
}
private void openAtt(String tag, String attributes) {
out.println(indent + "<" + tag + " " + attributes + ">");
indent += " ";
}
/*private void inline(String tag, String attributes) {
out.println(indent + "<" + tag + " " + attributes + " />");
}*/
private void close(String tag) {
indent = indent.substring(2);
out.print(indent + "</" + tag + ">");
}
private void closeln(String tag) {
close(tag);
out.println();
}
/**
* if content not null, open tag, write encoded content, and close tag
* else do nothing.
*/
private void simpleTag(String tag, String content) {
if (content != null && content.length() > 0) {
open(tag);
out.print(encode(content));
//out.print(content);
out.println("</" + tag + ">");
indent = indent.substring(2);
}
}
}