/* Name: - BusinessDataLoader Description: - Requires: - Provides: - Part of: ProcessPuzzle Framework, Domain and Business Model Ready Architecture. Provides content, workflow and social networking functionality. http://www.processpuzzle.com ProcessPuzzle - Content and Workflow Management Integration Business Platform Author(s): - Zsolt Zsuffa Copyright: (C) 2011 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 com.processpuzzle.business.definition.domain; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.ParameterizedType; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; import javax.xml.bind.UnmarshallerHandler; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; import org.springframework.oxm.XmlMappingException; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.XMLFilter; import org.xml.sax.XMLReader; import com.processpuzzle.application.resource.domain.DataLoaderException; import com.processpuzzle.application.resource.domain.XmlDataLoader; import com.processpuzzle.application.resource.domain.XmlDataLoaderException; import com.processpuzzle.persistence.domain.DefaultUnitOfWork; public abstract class BusinessDataLoader<D> extends XmlDataLoader { protected String mappingKey; protected String mappingPath; protected String schemaKey; protected Schema schema; protected Class<D> unmarshalledDataClass; protected D unmarshalledData; private InputSource inputSource; @SuppressWarnings( "unchecked" ) public BusinessDataLoader( ResourceLoader resourceLoader, String resourcePath ) { super( resourceLoader, resourcePath ); this.resultInPersistentObjects = true; unmarshalledDataClass = (Class<D>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; } @Override public void loadData() throws XmlDataLoaderException { super.loadData(); mappingPath = (String) applicationContext.getProperty( mappingKey ); try{ schema = loadSchema(); unmarshallXmlWithSpring(); DefaultUnitOfWork work = new DefaultUnitOfWork( true ); saveObjects( work ); work.finish(); }catch( BusinessDataSchemaException e ){ throw new XmlDataLoaderException( this, "Found problems with the associated schema.", e ); }catch( BusinessDataLoaderException e ){ throw new XmlDataLoaderException( this, "Found problems with the source data.", e ); } } protected abstract void saveObjects( DefaultUnitOfWork work ); private Schema loadSchema() throws BusinessDataSchemaException { schemaPath = applicationContext.getProperty( schemaKey ); InputStream resourceStream = null; Schema businessDataSchema = null; try{ resourceStream = resource.getInputStream(); }catch( IOException e ){ throw new BusinessDataSchemaException( schemaPath, e ); } if( resourceStream == null ) throw new DataLoaderException( this, "Can't load resource: " + resourcePath ); String language = javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI; SchemaFactory factory = SchemaFactory.newInstance( language ); factory.setErrorHandler( new BusinessDataLoaderErrorHandler( schemaPath ) ); factory.setResourceResolver( new SchemaResourceResolver( schemaPath, resourceLoader ) ); try{ Resource schemaResource = resourceLoader.getResource( schemaPath ); StreamSource schemaSource = new StreamSource( schemaResource.getInputStream() ); businessDataSchema = factory.newSchema( schemaSource ); }catch( SAXException e ){ throw new BusinessDataSchemaException( schemaPath, e ); }catch( IOException e ){ throw new BusinessDataSchemaException( schemaPath, e ); }catch( Exception e ){ throw new BusinessDataSchemaException( schemaPath, e ); } return businessDataSchema; } private void openInputSource( String resourcePath ) { InputStream resourceStream = null; try{ resourceStream = resource.getInputStream(); inputSource = new InputSource( resourceStream ); }catch( IOException e ){ throw new BusinessDataLoaderException( resourcePath, e ); } } @SuppressWarnings( "unchecked" ) private void unmarshallXmlWithSpring(){ org.springframework.oxm.Unmarshaller unmarshaller = (org.springframework.oxm.Unmarshaller) applicationContext.getBean( "jaxb2Unmarshaller" ); openInputSource( resourcePath ); try{ unmarshalledData = (D) unmarshaller.unmarshal( new StreamSource( resource.getFile() )); }catch( XmlMappingException | IOException e ){ e.printStackTrace(); } } @SuppressWarnings( { "unchecked", "unused" } ) private void unmarshallXml( String resourcePath ) throws BusinessDataLoaderException { openInputSource( resourcePath ); JAXBContext jaxbContext = null; try{ jaxbContext = JAXBContext.newInstance( new Class[] { unmarshalledDataClass } ); try{ final XMLFilter filter = new NamespaceFilter(); final SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); saxParserFactory.setNamespaceAware( true ); final SAXParser saxParser = saxParserFactory.newSAXParser(); final XMLReader reader = saxParser.getXMLReader(); filter.setParent( reader ); Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); unmarshaller.setSchema( schema ); unmarshaller.setEventHandler( new BusinessDataValidationEventHandler( resourcePath, schemaPath ) ); UnmarshallerHandler unmarshallerHandler = unmarshaller.getUnmarshallerHandler(); filter.setContentHandler( unmarshallerHandler ); filter.parse( inputSource ); unmarshalledData = (D) unmarshallerHandler.getResult(); }catch( SAXException | ParserConfigurationException e ){ throw new RuntimeException( e ); } }catch( JAXBException e ){ throw new BusinessDataLoaderException( resourcePath, e ); }catch( Exception e ){ throw new BusinessDataLoaderException( resourcePath, e ); } } }