package protobuf.codec.xml; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; import org.apache.commons.codec.binary.Base64; import protobuf.codec.AbstractCodec; import protobuf.codec.Codec.Feature; import com.google.protobuf.Descriptors.EnumValueDescriptor; import com.google.protobuf.Descriptors.FieldDescriptor; import com.google.protobuf.ByteString; import com.google.protobuf.Message; import com.google.protobuf.UnknownFieldSet; /** * * @author sijuv * */ public class XmlWriter { public static void writeXml(Message message, XMLStreamWriter xmlwriter, Map<Feature, Object> featureMap) throws XMLStreamException, IOException { Iterator<Map.Entry<FieldDescriptor, Object>> iterator = message.getAllFields().entrySet().iterator(); // Get all set fields while (iterator.hasNext()) { Map.Entry<FieldDescriptor, Object> record = iterator.next(); FieldDescriptor field = record.getKey(); String fieldName = field.isExtension() ? AbstractCodec.getExtensionFieldName(field.getName(), featureMap) : field.getName(); fieldName = AbstractCodec.substituteFieldNameForWriting(fieldName, featureMap); Object value = record.getValue(); if (field.isRepeated()) { Iterator<?> iter = ((List<?>) value).iterator(); while (iter.hasNext()) { xmlwriter.writeStartElement(fieldName); writeFieldValue(field, iter.next(), xmlwriter, featureMap); xmlwriter.writeEndElement(); } } else { xmlwriter.writeStartElement(fieldName); writeFieldValue(field, value, xmlwriter, featureMap); xmlwriter.writeEndElement(); } } if (AbstractCodec.supportUnknownFields(featureMap)) { writeUnknownFields(message.getUnknownFields(), xmlwriter, featureMap); } } // Extract the field value depending on its java type private static void writeFieldValue(FieldDescriptor fieldDesc, Object value, XMLStreamWriter writer, Map<Feature, Object> featureMap) throws XMLStreamException, IOException { switch (fieldDesc.getJavaType()) { case INT: case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case STRING: writer.writeCharacters(value.toString()); break; case ENUM: writer.writeCharacters(((EnumValueDescriptor) value).getName()); break; case BYTE_STRING: writer.writeCharacters(Base64.encodeBase64String(((ByteString) value).toByteArray())); break; case MESSAGE: writeXml((Message) value, writer, featureMap); break; default: throw new UnsupportedEncodingException( String.format( "Unspupported protobuf java field type [%s] for field [%s] ", fieldDesc.getJavaType(), fieldDesc.getName())); } } public static void writeUnknownFields(UnknownFieldSet unknownFields, XMLStreamWriter xmlwriter, Map<Feature, Object> featureMap) throws XMLStreamException { if (unknownFields != null && unknownFields.asMap().size() > 0) { xmlwriter.writeStartElement(AbstractCodec.getUnknownFieldElementName(featureMap)); xmlwriter.writeCharacters(AbstractCodec.encodeUnknownFieldsToString(unknownFields)); xmlwriter.writeEndElement(); } } }