package com.revolsys.record.io.format.xml; import java.util.List; import java.util.Map; import java.util.Map.Entry; import javax.xml.namespace.QName; import com.revolsys.collection.NameProxy; import com.revolsys.datatype.DataType; import com.revolsys.io.AbstractRecordWriter; import com.revolsys.io.FileUtil; import com.revolsys.io.IoConstants; import com.revolsys.record.Record; import com.revolsys.record.property.RecordProperties; import com.revolsys.record.schema.FieldDefinition; import com.revolsys.record.schema.RecordDefinition; public class XmlRecordWriter extends AbstractRecordWriter { private boolean opened; private XmlWriter out; private final RecordDefinition recordDefinition; private boolean singleObject; boolean startAttribute; public XmlRecordWriter(final RecordDefinition recordDefinition, final java.io.Writer out) { this.recordDefinition = recordDefinition; if (out instanceof XmlWriter) { this.out = (XmlWriter)out; } else { this.out = new XmlWriter(out); } } /** * Closes the underlying reader. */ @Override public void close() { if (this.out != null) { try { if (this.opened) { if (!this.singleObject) { this.out.endTag(); } this.out.endDocument(); } } finally { FileUtil.closeSilent(this.out); this.out = null; } } } @Override public void flush() { this.out.flush(); } @SuppressWarnings("unchecked") private void list(final List<? extends Object> list) { for (final Object value : list) { if (value instanceof Map) { final Map<String, ?> map = (Map<String, ?>)value; map(map); } else if (value instanceof List) { final List<?> subList = (List<?>)value; list(subList); } else { this.out.startTag(new QName("item")); this.out.text(value); this.out.endTag(); } } } @SuppressWarnings("unchecked") private void map(final Map<String, ? extends Object> values) { if (values instanceof NameProxy) { final NameProxy namedObject = (NameProxy)values; this.out.startTag(new QName(namedObject.getName())); } else { this.out.startTag(new QName("item")); } for (final Entry<String, ? extends Object> field : values.entrySet()) { final Object key = field.getKey(); final Object value = field.getValue(); final QName tagName = new QName(key.toString()); if (value instanceof Map) { final Map<String, ?> map = (Map<String, ?>)value; this.out.startTag(tagName); map(map); this.out.endTag(); } else if (value instanceof List) { final List<?> list = (List<?>)value; this.out.startTag(tagName); list(list); this.out.endTag(); } else { this.out.nillableElement(tagName, value); } } this.out.endTag(); } @Override public String toString() { return this.recordDefinition.getPath().toString(); } @Override public void write(final Record record) { if (!this.opened) { writeHeader(); } QName qualifiedName = this.recordDefinition.getProperty(RecordProperties.QUALIFIED_NAME); if (qualifiedName == null) { qualifiedName = new QName(this.recordDefinition.getName()); } this.out.startTag(qualifiedName); for (final FieldDefinition field : this.recordDefinition.getFields()) { final int fieldIndex = field.getIndex(); final Object value; if (isWriteCodeValues()) { value = record.getCodeValue(fieldIndex); } else { value = record.getValue(fieldIndex); } if (isValueWritable(value)) { final String name = field.getName(); final QName tagName = new QName(name); if (value instanceof Map) { @SuppressWarnings("unchecked") final Map<String, ?> map = (Map<String, ?>)value; this.out.startTag(tagName); map(map); this.out.endTag(); } else if (value instanceof List) { final List<?> list = (List<?>)value; this.out.startTag(tagName); list(list); this.out.endTag(); } else { final DataType dataType = field.getDataType(); final String string = dataType.toString(value); this.out.nillableElement(tagName, string); } } } this.out.endTag(); } private void writeHeader() { setIndent(isIndent()); this.out.startDocument("UTF-8", "1.0"); this.singleObject = Boolean.TRUE.equals(getProperty(IoConstants.SINGLE_OBJECT_PROPERTY)); if (!this.singleObject) { this.out.startTag(new QName("items")); } this.opened = true; } }