/**
* Copyright Intellectual Reserve, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.gedcomx.fileformat;
import org.gedcomx.Gedcomx;
import org.gedcomx.rt.GedcomNamespaceManager;
import org.gedcomx.rt.GedcomxConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
/**
* A class for creating instances of <code>JAXBContext</code> appropriate for reading and writing GEDCOM X files.
*/
public class JaxbXmlSerialization implements GedcomxEntrySerializer, GedcomxEntryDeserializer {
private final Unmarshaller unmarshaller;
private final Marshaller marshaller;
public JaxbXmlSerialization(Class<?>... classes) {
this(true, classes);
}
public JaxbXmlSerialization(boolean pretty, Class<?>... classes) {
try {
JAXBContext context = newContext(classes);
this.unmarshaller = context.createUnmarshaller();
this.marshaller = context.createMarshaller();
this.marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", new GedcomNamespaceManager(Gedcomx.class));
if (pretty) {
this.marshaller.setProperty("jaxb.formatted.output", Boolean.TRUE);
}
}
catch (JAXBException e) {
throw new IllegalArgumentException(e);
}
}
@Override
public Object deserialize(InputStream in, String mediaType) throws IOException {
if (!isKnownContentType(mediaType)) {
return in;
}
try {
return this.unmarshaller.unmarshal(in);
}
catch (JAXBException e) {
throw new IOException(e);
}
}
private boolean isKnownContentType(String mediaType) {
return mediaType.endsWith("xml");
}
@Override
public void serialize(Object resource, OutputStream out) throws IOException {
try {
this.marshaller.marshal(resource, out);
}
catch (JAXBException e) {
throw new IOException(e);
}
}
/**
* Factory method for creating a new instance of a <code>JAXBContext</code> appropriate for reading and/or writing a GEDCOM X file.
*
* The created <code>JAXBContext</code> references the following classes by default:
* org.gedcomx.conclusion.Person
* org.gedcomx.conclusion.Relationship
* org.gedcomx.metadata.dc.ObjectFactory
* org.gedcomx.metadata.foaf.Person
* org.gedcomx.contributor.Agent
* org.gedcomx.metadata.rdf.Description
* Any additional classes needed can be passed to this call to supplement (not override) these defaults
*
* @param classes Additional classes to supplement (not override) the provided defaults
* @return A JAXBContext
*
* @throws JAXBException
*/
private static JAXBContext newContext(Class<?>... classes) throws JAXBException {
Set<Class<?>> contextClasses = new HashSet<Class<?>>();
contextClasses.add(Gedcomx.class);
contextClasses.addAll(Arrays.asList(classes));
return JAXBContext.newInstance((Class<?>[]) contextClasses.toArray(new Class<?>[contextClasses.size()]));
}
@Override
public String suggestFilenameExtension() {
return ".xml";
}
}