/*
* Copyright (C) 2011 SeqWare
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.sourceforge.seqware.common.util.xmltools;
import java.io.Reader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import net.sourceforge.seqware.common.model.Experiment;
import net.sourceforge.seqware.common.model.ExperimentAttribute;
import net.sourceforge.seqware.common.model.ExperimentLibraryDesign;
import net.sourceforge.seqware.common.model.ExperimentSpotDesign;
import net.sourceforge.seqware.common.model.ExperimentSpotDesignReadSpec;
import net.sourceforge.seqware.common.model.File;
import net.sourceforge.seqware.common.model.FileType;
import net.sourceforge.seqware.common.model.IUS;
import net.sourceforge.seqware.common.model.IUSAttribute;
import net.sourceforge.seqware.common.model.Lane;
import net.sourceforge.seqware.common.model.LaneAttribute;
import net.sourceforge.seqware.common.model.LibrarySelection;
import net.sourceforge.seqware.common.model.LibrarySource;
import net.sourceforge.seqware.common.model.LibraryStrategy;
import net.sourceforge.seqware.common.model.Organism;
import net.sourceforge.seqware.common.model.Platform;
import net.sourceforge.seqware.common.model.Processing;
import net.sourceforge.seqware.common.model.ProcessingAttribute;
import net.sourceforge.seqware.common.model.Registration;
import net.sourceforge.seqware.common.model.Sample;
import net.sourceforge.seqware.common.model.SampleAttribute;
import net.sourceforge.seqware.common.model.SequencerRun;
import net.sourceforge.seqware.common.model.SequencerRunWizardDTO;
import net.sourceforge.seqware.common.model.Study;
import net.sourceforge.seqware.common.model.StudyAttribute;
import net.sourceforge.seqware.common.model.StudyType;
import net.sourceforge.seqware.common.model.Workflow;
import net.sourceforge.seqware.common.model.WorkflowParam;
import net.sourceforge.seqware.common.model.WorkflowParamValue;
import net.sourceforge.seqware.common.model.WorkflowRun;
import net.sourceforge.seqware.common.model.WorkflowRunParam;
import net.sourceforge.seqware.common.model.lists.ExperimentLibraryDesignList;
import net.sourceforge.seqware.common.model.lists.ExperimentList;
import net.sourceforge.seqware.common.model.lists.ExperimentSpotDesignList;
import net.sourceforge.seqware.common.model.lists.ExperimentSpotDesignReadSpecList;
import net.sourceforge.seqware.common.model.lists.FileList;
import net.sourceforge.seqware.common.model.lists.IUSList;
import net.sourceforge.seqware.common.model.lists.IntegerList;
import net.sourceforge.seqware.common.model.lists.LaneList;
import net.sourceforge.seqware.common.model.lists.LibrarySelectionList;
import net.sourceforge.seqware.common.model.lists.LibrarySourceList;
import net.sourceforge.seqware.common.model.lists.LibraryStrategyList;
import net.sourceforge.seqware.common.model.lists.OrganismList;
import net.sourceforge.seqware.common.model.lists.PlatformList;
import net.sourceforge.seqware.common.model.lists.ProcessingList;
import net.sourceforge.seqware.common.model.lists.ReturnValueList;
import net.sourceforge.seqware.common.model.lists.SampleList;
import net.sourceforge.seqware.common.model.lists.SequencerRunList;
import net.sourceforge.seqware.common.model.lists.StudyList;
import net.sourceforge.seqware.common.model.lists.StudyTypeList;
import net.sourceforge.seqware.common.model.lists.WorkflowList;
import net.sourceforge.seqware.common.model.lists.WorkflowParamList;
import net.sourceforge.seqware.common.model.lists.WorkflowParamValueList;
import net.sourceforge.seqware.common.model.lists.WorkflowRunList;
import net.sourceforge.seqware.common.model.lists.WorkflowRunList2;
import org.w3c.dom.Document;
/**
* Convenience class for converting objects into JAXB XML.
*
* @author mtaschuk
* @version $Id: $Id
* @param <T>
*/
public class JaxbObject<T> {
private static JAXBContext context = null;
/**
* JAXB has a memory leak when it comes to making new JAXBContext instances, so one JAXBContext is created for the entire lifetime of
* the program and initialized with all of the classes that we marshal and unmarshal at the moment, as per the instructions at *
* http://whileonefork.blogspot.com/2010/09/leaking-of-jaxb.html and * http://jaxb.java.net/guide/Performance_and_thread_safety.html .
* In order to marshall or unmarshall new objects, they must be added to the context creation in this constructor.
*/
public JaxbObject() {
try {
if (context == null) {
context = JAXBContext.newInstance(
Experiment.class,
ExperimentAttribute.class,
ExperimentLibraryDesign.class, // ExperimentLink.class,
ExperimentSpotDesign.class,
ExperimentSpotDesignReadSpec.class,
File.class,
FileType.class,
IUS.class,
IUSAttribute.class,
Lane.class,
LaneAttribute.class,
LibrarySelection.class,
LibrarySource.class,
LibraryStrategy.class,
Organism.class,
Platform.class,
Processing.class,
ProcessingAttribute.class,
// ProcessingExperiments.class, ProcessingIus.class,
// ProcessingLanes.class, ProcessingRelationship.class, ProcessingSamples.class,
// ProcessingSequencerRuns.class, ProcessingStudies.class,
Registration.class,
Sample.class,
SampleAttribute.class,
SequencerRun.class,
SequencerRunWizardDTO.class,
// ShareExperiment.class, ShareFile.class, ShareLane.class,
// ShareProcessing.class, ShareSample.class, ShareStudy.class, ShareWorkflowRun.class,
Study.class, StudyAttribute.class, StudyType.class, Workflow.class, WorkflowParam.class,
WorkflowParamValue.class, WorkflowRun.class, WorkflowRunParam.class, ExperimentList.class,
ExperimentLibraryDesignList.class, ExperimentSpotDesignList.class, ExperimentSpotDesignReadSpecList.class,
FileList.class, IUSList.class, LaneList.class, LibrarySelectionList.class, LibrarySourceList.class,
LibraryStrategyList.class, OrganismList.class, PlatformList.class, ProcessingList.class, ReturnValueList.class,
SampleList.class, SequencerRunList.class, StudyList.class, StudyTypeList.class, WorkflowList.class,
WorkflowRunList.class, WorkflowRunList2.class, WorkflowParamList.class, WorkflowParamValueList.class,
ArrayList.class, IntegerList.class);
}
} catch (JAXBException e) {
e.printStackTrace();
}
}
/**
* Turn an object into XML using JAXB and provide the result in a StreamResult.
*
* @param t
* The object to XMLize.
* @return the XML. The StreamResult was created with a StringWriter, which can be used to retrieve the XML.
* @throws javax.xml.bind.JAXBException
* if any.
*/
public Document marshalToDocument(T t) throws JAXBException {
Document doc = null;
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder db = dbf.newDocumentBuilder();
doc = db.newDocument();
T object = t;
// get the XML
// JAXBContext context = JAXBContext.newInstance(object.getClass());
Marshaller m = context.createMarshaller();
m.marshal(new JAXBElement(new QName(object.getClass().getSimpleName()), object.getClass(), object), doc);
// try {
// XmlTools.getDocument(output);
// } catch (Exception ex) {
// Log.info("Exception while marshaling: " + ex.getMessage() + ". Trying again.");
// output = marshal(t);
// }
} catch (ParserConfigurationException ex) {
Logger.getLogger(JaxbObject.class.getName()).log(Level.SEVERE, null, ex);
} catch (JAXBException jbe) {
jbe.printStackTrace();
throw jbe;
}
return doc;
}
/**
* Turn an object into XML using JAXB and provide the result in a StreamResult.
*
* @param t
* The object to XMLize.
* @return the XML. The StreamResult was created with a StringWriter, which can be used to retrieve the XML.
* @throws javax.xml.bind.JAXBException
* if any.
*/
public String marshal(T t) throws JAXBException {
String output = null;
try {
StreamResult result = new StreamResult(new StringWriter());
T object = t;
// get the XML
// JAXBContext context = JAXBContext.newInstance(object.getClass());
Marshaller m = context.createMarshaller();
m.marshal(new JAXBElement(new QName(object.getClass().getSimpleName()), object.getClass(), object), result);
// convert to String
StringWriter writer = (StringWriter) result.getWriter();
StringBuffer buffer = writer.getBuffer();
output = buffer.toString();
// try {
// XmlTools.getDocument(output);
// } catch (Exception ex) {
// Log.info("Exception while marshaling: " + ex.getMessage() + ". Trying again.");
// output = marshal(t);
// }
} catch (JAXBException jbe) {
jbe.printStackTrace();
throw jbe;
}
return output;
}
/**
* Turn an XML stream into an object, if possible.
*
* @param expectedType
* a T object.
* @param reader
* a {@link java.io.Reader} object.
* @return a T object.
* @throws javax.xml.bind.JAXBException
* if any.
*/
public T unMarshal(T expectedType, Reader reader) throws JAXBException {
T object = null;
try {
// JAXBContext context = JAXBContext.newInstance(expectedType.getClass());
Unmarshaller m = context.createUnmarshaller();
JAXBElement o = m.unmarshal(new StreamSource(reader), expectedType.getClass());
object = (T) o.getValue();
} catch (JAXBException jbe) {
jbe.printStackTrace();
throw jbe;
}
return object;
}
/**
* Turn an XML stream into an object, if possible.
*
* @param expectedType
* a T object.
* @param d
* a {@link org.w3c.dom.Document} object.
* @return a T object.
* @throws javax.xml.bind.JAXBException
* if any.
*/
public T unMarshal(Document d, T expectedType) throws JAXBException {
T object = null;
try {
// JAXBContext context = JAXBContext.newInstance(expectedType.getClass());
Unmarshaller m = context.createUnmarshaller();
JAXBElement o = m.unmarshal(d, expectedType.getClass());
object = (T) o.getValue();
} catch (JAXBException jbe) {
jbe.printStackTrace();
throw jbe;
}
return object;
}
}