/**
* Copyright (c) Codice Foundation
* <p/>
* This is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either
* version 3 of the License, or any later version.
* <p/>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details. A copy of the GNU Lesser General Public License is distributed along with this program and can be found at
* <http://www.gnu.org/licenses/lgpl.html>.
*/
package ddf.catalog.services.transformer.xml;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.Map;
import java.util.Set;
import javax.activation.MimeType;
import javax.activation.MimeTypeParseException;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.transform.TransformerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ddf.catalog.data.AttributeDescriptor;
import ddf.catalog.data.AttributeType.AttributeFormat;
import ddf.catalog.data.BinaryContent;
import ddf.catalog.data.BinaryContentImpl;
import ddf.catalog.data.Metacard;
import ddf.catalog.services.transformer.xml.schema.Binary;
import ddf.catalog.services.transformer.xml.schema.ObjectFactory;
import ddf.catalog.services.transformer.xml.schema.Text;
import ddf.catalog.transform.CatalogTransformerException;
import ddf.catalog.transform.MetacardTransformer;
public class XmlMetacardTransformer implements MetacardTransformer {
private static final String TEXT_XML = "text/xml";
private static final String CDATA_OPENING = "<![CDATA[";
private static final String CDATA_CLOSING = "]]>";
private static final Logger LOGGER = LoggerFactory.getLogger(XmlMetacardTransformer.class);
private static JAXBContext jc;
private TransformerFactory factory;
public XmlMetacardTransformer() {
factory = TransformerFactory.newInstance();
}
@Override
public BinaryContent transform(Metacard metacard, Map<String, Serializable> arguments)
throws CatalogTransformerException {
BinaryContent transformedContent = null;
if (metacard == null) {
LOGGER.warn("Attmpted to transform null metacard");
throw new CatalogTransformerException("Unable to transform null metacard");
}
Set<AttributeDescriptor> descriptors = metacard.getMetacardType().getAttributeDescriptors();
ObjectFactory of = new ObjectFactory();
ddf.catalog.services.transformer.xml.schema.Metacard xmlMetacard = of.createMetacard();
for (AttributeDescriptor descriptor : descriptors) {
AttributeFormat format = descriptor.getType().getAttributeFormat();
String name = descriptor.getName();
switch (format) {
case STRING:
Text textPayload = new Text();
textPayload.setName(name);
if (metacard.getAttribute(name) != null) {
textPayload.setValue((String) metacard.getAttribute(name).getValue());
xmlMetacard.getText().add(textPayload);
}
break;
case BOOLEAN:
textPayload = new Text();
textPayload.setName(name);
if (metacard.getAttribute(name) != null) {
textPayload.setValue((String) metacard.getAttribute(name).getValue());
xmlMetacard.getBoolean().add(textPayload);
}
break;
case DATE:
textPayload = new Text();
textPayload.setName(name);
if (metacard.getAttribute(name) != null) {
textPayload
.setValue((String) metacard.getAttribute(name).getValue().toString());
xmlMetacard.getDate().add(textPayload);
}
break;
case SHORT:
textPayload = new Text();
textPayload.setName(name);
if (metacard.getAttribute(name) != null) {
textPayload.setValue((String) metacard.getAttribute(name).getValue());
xmlMetacard.getShort().add(textPayload);
}
break;
case INTEGER:
textPayload = new Text();
textPayload.setName(name);
if (metacard.getAttribute(name) != null) {
textPayload.setValue((String) metacard.getAttribute(name).getValue());
xmlMetacard.getInteger().add(textPayload);
}
break;
case LONG:
textPayload = new Text();
textPayload.setName(name);
if (metacard.getAttribute(name) != null) {
textPayload.setValue((String) metacard.getAttribute(name).getValue());
xmlMetacard.getLong().add(textPayload);
}
break;
case FLOAT:
textPayload = new Text();
textPayload.setName(name);
if (metacard.getAttribute(name) != null) {
textPayload.setValue((String) metacard.getAttribute(name).getValue());
xmlMetacard.getFloat().add(textPayload);
}
break;
case DOUBLE:
textPayload = new Text();
textPayload.setName(name);
if (metacard.getAttribute(name) != null) {
textPayload.setValue((String) metacard.getAttribute(name).getValue());
xmlMetacard.getDouble().add(textPayload);
}
break;
case GEOMETRY:
textPayload = new Text();
textPayload.setName(name);
if (metacard.getAttribute(name) != null) {
textPayload.setValue((String) metacard.getAttribute(name).getValue());
xmlMetacard.getGeometry().add(textPayload);
}
break;
case BINARY:
Binary binaryPayload = new Binary();
binaryPayload.setName(name);
if (metacard.getAttribute(name) != null) {
ByteArrayOutputStream finalByteArray = new ByteArrayOutputStream();
try {
finalByteArray.write(CDATA_OPENING.getBytes("UTF-8"));
finalByteArray.write((byte[]) metacard.getAttribute(name).getValue());
finalByteArray.write(CDATA_CLOSING.getBytes("UTF-8"));
} catch (IOException e) {
LOGGER.error("IOException building byte array.", e);
}
binaryPayload.setValue(finalByteArray.toByteArray());
xmlMetacard.getBinary().add(binaryPayload);
}
break;
case XML:
textPayload = new Text();
textPayload.setName(name);
if (metacard.getAttribute(name) != null) {
textPayload.setValue(CDATA_OPENING +
(String) metacard.getAttribute(name).getValue() +
CDATA_CLOSING);
xmlMetacard.getTextXml().add(textPayload);
}
break;
case OBJECT:
binaryPayload = new Binary();
binaryPayload.setName(name);
if (metacard.getAttribute(name) != null) {
ByteArrayOutputStream finalByteArray = new ByteArrayOutputStream();
try {
finalByteArray.write(CDATA_OPENING.getBytes("UTF-8"));
finalByteArray.write((byte[]) metacard.getAttribute(name).getValue());
finalByteArray.write(CDATA_CLOSING.getBytes("UTF-8"));
} catch (IOException e) {
LOGGER.error("IOException building byte array.", e);
}
binaryPayload.setValue(finalByteArray.toByteArray());
xmlMetacard.getObject().add(binaryPayload);
}
break;
default:
throw new RuntimeException("Attribute format is not recognized");
}
}
if (jc == null) {
try {
jc = JAXBContext
.newInstance(ddf.catalog.services.transformer.xml.schema.Metacard.class);
} catch (JAXBException e) {
LOGGER.error("JAXB error: ", e);
}
}
ClassLoader tccl = Thread.currentThread().getContextClassLoader();
try {
Marshaller marshaller = jc.createMarshaller();
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
ByteArrayOutputStream os = new ByteArrayOutputStream();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(xmlMetacard, os);
ByteArrayInputStream bais = new ByteArrayInputStream(os.toByteArray());
transformedContent = new BinaryContentImpl(bais, new MimeType(TEXT_XML));
} catch (JAXBException e) {
LOGGER.error("JAXB error: ", e);
} catch (MimeTypeParseException e) {
LOGGER.error("MimeType Parsing error: ", e);
} finally {
Thread.currentThread().setContextClassLoader(tccl);
}
return transformedContent;
}
}