package jeql.command.io; import java.io.IOException; import java.io.Writer; import jeql.api.row.Row; import jeql.api.row.RowIterator; import jeql.api.row.RowSchema; import jeql.api.row.RowUtil; import jeql.api.table.Table; import jeql.command.io.TableFileWriterCmd; import jeql.command.io.xml.XmlDataWriter; import jeql.engine.Scope; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.io.gml2.GMLWriter; public class GMLWriterCommand extends TableFileWriterCmd { private static final String TBL_ROW_TAGS_SEPARATOR = "_"; public static final String GML_FEATURECOLLECTION_TAG = "gml:FeatureCollection"; public static final String GML_FEATUREMEMBER_TAG = "gml:featureMember"; public static final String GML_FEATURE_TAG = "gml:Feature"; public static final String GML_NAMESPACE_ATTR = "xmlns:gml=\"http://www.opengis.net/gml\""; private String comment = null; private static String featureMemberTag = GML_FEATUREMEMBER_TAG; private String featureCollectionTag = GML_FEATURECOLLECTION_TAG; private String featureTag = GML_FEATURE_TAG; private String userNamespacePrefix = null; private String userNamespaceURI = null; private String gmlIdColumn = "gml_id"; private RowSchema schema = null; private XmlDataWriter xmlWriter; private GMLWriter gmlWriter = new GMLWriter(); public GMLWriterCommand() { super(); } /** * Sets the name to use as the table tag name. * Name string may contain multiple tags separated by TBL_ROW_TAGS_SEPARATOR. * Multiple tags will be written as nested elements. * * @param tableTag */ public void setFeatureCollectionTag(String tableTag) { this.featureCollectionTag = tableTag; } public void setNamespacePrefix(String userNamespacePrefix) { this.userNamespacePrefix = userNamespacePrefix; } public void setNamespaceURI(String userNamespaceURI) { this.userNamespaceURI = userNamespaceURI; } /** * Sets the name to use as the row tag name. * Name string may contain multiple tags separated by TBL_ROW_TAGS_SEPARATOR. * Multiple tags will be written as nested elements. * * @param rowTag */ public void setFeatureTag(String rowTag) { this.featureTag = rowTag; } public void setIdColumn(String gmlIdColumn) { this.gmlIdColumn = gmlIdColumn; } /** * Sets comment text to write at start of document * @param comment */ public void setComment(String comment) { this.comment = comment; } /** * Attributes string to write in table tag * @param tableAttr */ /* public void setTableAttr(String tableAttr) { this.tableAttr = tableAttr; } */ public void execute(Scope scope) throws Exception { writer = getWriter(); xmlWriter = new XmlDataWriter(writer); xmlWriter.prolog(); if (comment != null) xmlWriter.comment(comment); String tableAttr = GML_NAMESPACE_ATTR; if (userNamespacePrefix != null && userNamespaceURI != null) tableAttr += " " + "xmlns:" + userNamespacePrefix +"=" + "\"" + userNamespaceURI + "\""; // write table int n = writeStartElements(featureCollectionTag, tableAttr); write(tbl); writeEndElements(n); writer.close(); } private int writeStartElements(String tag, String attr) throws IOException { String[] tags = tag.split(TBL_ROW_TAGS_SEPARATOR); for (int i = 0; i < tags.length; i++) { if (i == 0) xmlWriter.elementStart(tags[0], attr); else xmlWriter.elementStart(tags[i]); } return tags.length; } private void writeEndElements(int n) throws IOException { for (int i = 0; i < n; i++) { xmlWriter.elementEnd(); } } protected void write(Table tbl) throws Exception { schema = tbl.getRows().getSchema(); RowIterator rs = tbl.getRows().iterator(); while (true) { Row row = rs.next(); if (row == null) break; String fidAttr = null; Object fidVal = getFidValue(row); if (fidVal != null) fidAttr = "fid=\"" + fidVal + "\""; //int n = writeStartElements(featureTag, null); xmlWriter.elementStart(featureMemberTag); xmlWriter.elementStart(featureTag, fidAttr); writeRow(writer, row); //writeEndElements(n); xmlWriter.elementEnd(); xmlWriter.elementEnd(); } } private String getFidValue(Row row) { return RowUtil.getString(schema, gmlIdColumn, row); } private void writeRow(Writer writer, Row row) throws IOException { for (int i = 0; i < row.size(); i++) { String itemTag = schema.getName(i); // skip id value if (itemTag.equals(gmlIdColumn)) continue; String nsItemTag = addNamespace(itemTag, userNamespacePrefix); Object val = row.getValue(i); if (val instanceof String) { xmlWriter.elementWithData(nsItemTag, (String) val); } else if (val instanceof Geometry) { // indent geometry output xmlWriter.elementStart(nsItemTag); xmlWriter.markup(geometryRep((Geometry) val), true); xmlWriter.elementEnd(); // xmlWriter.elementWithDataRaw(itemTag, geometryRep((Geometry) val))); } else { // no need to encode non-string values -> faster xmlWriter.elementWithDataRaw(nsItemTag, val.toString()); } // TODO: better formatting for data items (eg Geometry, dates) ?? } } private String geometryRep(Geometry g) { return gmlWriter.write(g); } private String addNamespace(String tag, String ns) { if (tag.contains(":") || ns == null) return tag; return ns + ":" + tag; } }