2 * Copyright (C) 2008 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
10 package eu
.etaxonomy
.cdm
.io
.jaxb
;
13 import java
.io
.FileInputStream
;
14 import java
.io
.FileNotFoundException
;
15 import java
.io
.IOException
;
16 import java
.io
.InputStreamReader
;
17 import java
.io
.Reader
;
18 import java
.io
.UnsupportedEncodingException
;
19 import java
.io
.Writer
;
20 import java
.net
.URISyntaxException
;
22 import javax
.xml
.bind
.JAXBException
;
23 import javax
.xml
.bind
.Marshaller
;
24 import javax
.xml
.bind
.PropertyException
;
25 import javax
.xml
.parsers
.ParserConfigurationException
;
26 import javax
.xml
.parsers
.SAXParser
;
27 import javax
.xml
.parsers
.SAXParserFactory
;
28 import javax
.xml
.transform
.Source
;
29 import javax
.xml
.transform
.sax
.SAXResult
;
30 import javax
.xml
.transform
.sax
.SAXSource
;
31 import javax
.xml
.transform
.stream
.StreamResult
;
32 import javax
.xml
.validation
.Schema
;
33 import javax
.xml
.validation
.SchemaFactory
;
35 import org
.apache
.logging
.log4j
.LogManager
;
36 import org
.apache
.logging
.log4j
.Logger
;
37 import org
.apache
.xml
.resolver
.tools
.CatalogResolver
;
38 import org
.springframework
.core
.io
.ClassPathResource
;
39 import org
.springframework
.core
.io
.Resource
;
40 import org
.springframework
.oxm
.UncategorizedMappingException
;
41 import org
.springframework
.oxm
.XmlMappingException
;
42 import org
.springframework
.oxm
.jaxb
.Jaxb2Marshaller
;
43 import org
.xml
.sax
.InputSource
;
44 import org
.xml
.sax
.SAXException
;
45 import org
.xml
.sax
.XMLReader
;
46 import org
.xml
.sax
.helpers
.XMLReaderFactory
;
48 import eu
.etaxonomy
.cdm
.common
.URI
;
49 import eu
.etaxonomy
.cdm
.jaxb
.CdmNamespacePrefixMapper
;
50 import eu
.etaxonomy
.cdm
.jaxb
.FormattedText
;
51 import eu
.etaxonomy
.cdm
.jaxb
.MultilanguageTextElement
;
54 * Initializes a JaxbContext with one class (eu.etaxonomy.cdm.model.DataSet).
56 * @author a.babadshanjan, ben.clark
58 //Binds it to XML schemas found in /src/main/resources/schema/cdm (cdm.xsd, common.xsd, name.xsd).
59 //There is a bit of magic with a resource resolver in eu.etaxonomy.cdm.io.jaxb
60 //which allows to package the schemas into a jar file.
61 public class CdmDocumentBuilder
extends Jaxb2Marshaller
{
63 private static final Logger logger
= LogManager
.getLogger();
64 private boolean formattedOutput
= Boolean
.TRUE
;
65 private String encoding
= "UTF-8";
67 public static String CDM_NAMESPACE
= "eu.etaxonomy.cdm.model";
68 public static String
[] CDM_SCHEMA_FILES
= { "/schema/cdm/agent.xsd",
69 "/schema/cdm/cdm.xsd",
70 "/schema/cdm/common.xsd",
71 "/schema/cdm/description.xsd",
72 "/schema/cdm/location.xsd",
73 "/schema/cdm/media.xsd",
74 "/schema/cdm/molecular.xsd",
75 "/schema/cdm/name.xsd",
76 "/schema/cdm/occurrence.xsd",
77 "/schema/cdm/reference.xsd",
78 "/schema/cdm/taxon.xsd"};
79 public static Class
[] CONTEXT_CLASSES
= {
80 DataSet
.class,FormattedText
.class,MultilanguageTextElement
.class};
82 private Resource schemas
[];
84 protected String
[] getSchemaFiles() {
85 return CDM_SCHEMA_FILES
;
88 protected Class
[] getContextClasses() {
89 return CONTEXT_CLASSES
;
92 public CdmDocumentBuilder() {
93 schemas
= new Resource
[CDM_SCHEMA_FILES
.length
];
95 for(int i
= 0; i
< CDM_SCHEMA_FILES
.length
; i
++) {
96 schemas
[i
] = new ClassPathResource(CDM_SCHEMA_FILES
[i
]);
99 super.setSchemas(schemas
);
100 super.setClassesToBeBound(CONTEXT_CLASSES
);
101 super.setSchemaLanguage("http://www.w3.org/2001/XMLSchema");
104 public CdmDocumentBuilder(boolean formattedOutput
, String encoding
) {
105 this.formattedOutput
= formattedOutput
;
106 this.encoding
= encoding
;
111 protected void initJaxbMarshaller(Marshaller marshaller
) throws JAXBException
{
113 marshaller
.setProperty("com.sun.xml.bind.namespacePrefixMapper", new CdmNamespacePrefixMapper() );
115 // For test purposes insert newlines to make the XML output readable
116 marshaller
.setProperty(Marshaller
.JAXB_FORMATTED_OUTPUT
, formattedOutput
);
117 //marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION,"http://etaxonomy.eu/cdm/model/1.0 schema/cdm/cdm.xsd");
118 //marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION,"http://etaxonomy.eu/cdm/model/1.0 cdm.xsd");
119 marshaller
.setProperty(Marshaller
.JAXB_ENCODING
, encoding
);
121 CdmMarshallerListener marshallerListener
= new CdmMarshallerListener();
122 marshaller
.setListener(marshallerListener
);
123 marshaller
.setEventHandler(new WarningTolerantValidationEventHandler());
124 } catch(PropertyException pe
) {
125 throw new JAXBException(pe
.getMessage(),pe
);
129 protected <T
> T
unmarshal(Class
<T
> clazz
, InputSource input
) {
130 SAXParserFactory saxParserFactory
= SAXParserFactory
.newInstance();
133 schema
= createSchema();
134 saxParserFactory
.setNamespaceAware(true);
135 saxParserFactory
.setXIncludeAware(true);
136 saxParserFactory
.setValidating(true);
137 saxParserFactory
.setSchema(schema
);
139 SAXParser saxParser
= saxParserFactory
.newSAXParser();
140 XMLReader xmlReader
= saxParser
.getXMLReader();
141 xmlReader
.setEntityResolver(new CatalogResolver());
142 xmlReader
.setErrorHandler(new DefaultErrorHandler());
143 SAXSource saxSource
= new SAXSource( xmlReader
, input
);
144 saxSource
.setSystemId(input
.getSystemId());
146 return (T
)super.unmarshal(saxSource
);
147 } catch (IOException e
) {
148 throw new UncategorizedMappingException(e
.getMessage(), e
);
149 } catch (SAXException e
) {
150 throw new UncategorizedMappingException(e
.getMessage(), e
);
151 } catch (ParserConfigurationException e
) {
152 throw new UncategorizedMappingException(e
.getMessage(), e
);
156 private Schema
createSchema() throws SAXException
, IOException
{
157 //method created to avoid dependency of spring-xml like in earlier versions
158 //old implementation was schema = SchemaLoaderUtils.loadSchema(schemas, "http://www.w3.org/2001/XMLSchema");
159 //maybe we can improve this loading in future
161 String schemaLanguage
= "http://www.w3.org/2001/XMLSchema";
162 Source
[] schemaSources
= new Source
[schemas
.length
];
163 XMLReader reader
= XMLReaderFactory
.createXMLReader();
164 reader
.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
165 for (int i
= 0; i
< schemas
.length
; i
++) {
166 schemaSources
[i
] = makeSchemaSource(reader
, schemas
[i
]);// new ResourceSource(reader, schemas[i]);
168 SchemaFactory schemaFactory
= SchemaFactory
.newInstance(schemaLanguage
);
169 return schemaFactory
.newSchema(schemaSources
);
172 private Source
makeSchemaSource(XMLReader reader
, Resource resource
) throws IOException
{
173 Source result
= new SAXSource(reader
, createInputSource(resource
));
177 private static InputSource
createInputSource(Resource resource
) throws IOException
{
178 InputSource inputSource
= new InputSource(resource
.getInputStream());
179 inputSource
.setSystemId(getSystemId(resource
));
183 /** Retrieves the URL from the given resource as System ID. Returns <code>null</code> if it cannot be opened. */
184 private static String
getSystemId(Resource resource
) {
186 return new URI(resource
.getURL().toExternalForm()).toString();
188 catch (IOException ex
) {
189 logger
.debug("Could not get System ID from [" + resource
+ "], ex");
192 catch (URISyntaxException e
) {
193 logger
.debug("Could not get System ID from [" + resource
+ "], ex");
198 public <T
> T
unmarshal(Class
<T
> clazz
,Reader reader
) throws XmlMappingException
{
199 InputSource source
= new InputSource(reader
);
200 return unmarshal(clazz
,source
);
203 public <T
> T
unmarshal(Class
<T
> clazz
,Reader reader
, String systemId
) throws XmlMappingException
{
204 InputSource input
= new InputSource(reader
);
205 input
.setSystemId(systemId
);
206 return unmarshal(clazz
,input
);
209 public <T
> T
unmarshal(Class
<T
> clazz
, File file
) throws XmlMappingException
{
213 input
= new InputSource(new InputStreamReader(new FileInputStream(file
),encoding
));
214 return unmarshal(clazz
,input
);
215 } catch (UnsupportedEncodingException e
) {
216 throw new UncategorizedMappingException(e
.getMessage(), e
);
217 } catch (FileNotFoundException e
) {
218 throw new UncategorizedMappingException(e
.getMessage(), e
);
222 public void marshal(DataSet dataSet
, Writer writer
) throws XmlMappingException
{
223 logger
.info("Start marshalling");
224 super.marshal(dataSet
, new StreamResult(writer
));
227 public void marshal(DataSet dataSet
, StreamResult result
) throws XmlMappingException
{
228 logger
.info("Start marshalling");
229 super.marshal(dataSet
, result
);
232 public void marshal(DataSet dataSet
, SAXResult result
) throws XmlMappingException
{
233 logger
.info("Start marshalling");
234 super.marshal(dataSet
, result
);