package org.cloudgraph.web.etl; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.List; import javax.xml.bind.JAXBException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.cloudgraph.web.config.ImportExportConfig; import org.cloudgraph.web.config.imex.DataEntity; import org.cloudgraph.web.config.imex.DataExport; import org.jdom2.output.XMLOutputter; import org.plasma.common.bind.DataBinding; import org.plasma.common.bind.DefaultValidationEventHandler; import org.plasma.config.ConfigurationException; import org.plasma.query.bind.PlasmaQueryDataBinding; import org.plasma.query.model.Query; import org.plasma.sdo.access.client.PojoDataAccessClient; import org.plasma.sdo.access.client.SDODataAccessClient; import org.plasma.sdo.core.CoreXMLDocument; import org.plasma.sdo.helper.PlasmaXMLHelper; import org.plasma.sdo.helper.PlasmaXSDHelper; import org.plasma.sdo.xml.DefaultOptions; import org.plasma.sdo.xml.XMLOptions; import org.plasma.xml.uml.UMLModelAssembler; import org.xml.sax.SAXException; import org.plasma.config.DataAccessProviderName; import commonj.sdo.DataGraph; import commonj.sdo.helper.XMLDocument; public class DataExtract { private static Log log = LogFactory.getLog(DataExtract.class); private File baseExportDir = new File("./"); private File defaultExportDir = new File(baseExportDir, "export"); private File baseDataDir = new File("./"); public DataExtract(String[] args) throws JAXBException, SAXException, IOException { for (org.cloudgraph.web.config.imex.DataExport dataExport : ImportExportConfig.getInstance().getConfig().getDataExport()) { log.info("processing data export: " + dataExport.getName()); processDataEntities(dataExport, dataExport.getDataEntity(), dataExport.getTargetDir()); } } private void processDataEntities(DataExport export, List<DataEntity> list, String targetDir) throws IOException { for (DataEntity dataEntity : list) { File exportDir = defaultExportDir; if (dataEntity.getTargetDir() != null) { if (targetDir != null) { exportDir = new File(new File(baseExportDir, targetDir), dataEntity.getTargetDir()); } else { exportDir = new File(baseExportDir, dataEntity.getTargetDir()); } } else if (targetDir != null) { exportDir = new File(baseExportDir, targetDir); } else log.warn("no export dir defined, using '" + exportDir.getAbsolutePath() + "'"); exportDir.mkdirs(); if (dataEntity.getTargetNamespaceUri() == null || dataEntity.getTargetNamespaceUri().length() == 0) throw new IllegalArgumentException("expected target namespace URI for data entity"); File queryFile = new File(baseDataDir, dataEntity.getSource()); Query query = unmarshalQuery(queryFile); DataBinding binding = null; if (dataEntity.getDataBindingClassName() != null) try { binding = createDataBinding(dataEntity.getDataBindingClassName()); } catch (Throwable t) { throw new IllegalArgumentException(t); } File exportFile = null; if (dataEntity.getTarget() != null && dataEntity.getTarget().length() > 0) exportFile = new File(exportDir, dataEntity.getTarget()); processExport(export, dataEntity, query, binding, exportDir, exportFile); } } private DataBinding createDataBinding(String className) throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException { Class<?> c = Class.forName(className); Class<?>[] paramTypes = new Class[0]; Object[] args = new Object[0]; Constructor<?> constructor = c.getConstructor(paramTypes); DataBinding result = (DataBinding)constructor.newInstance(args); return result; } private void processExport(DataExport export, DataEntity dataEntity, Query query, DataBinding dataBinding, File exportDir, File exportFile) throws IOException { try { PlasmaQueryDataBinding binding = new PlasmaQueryDataBinding( new DefaultValidationEventHandler()); log.info("marshaling query"); String xml = binding.marshal(query); log.info("validating marshaled query"); query = (Query)binding.validate(xml); assert(query != null); log.debug(xml); } catch (JAXBException e) { log.error(e.getMessage(), e); throw new RuntimeException(e); } catch (SAXException e) { log.error(e.getMessage(), e); throw new RuntimeException(e); }catch (Exception e) { log.error(e.getMessage(), e); throw new RuntimeException(e); } log.info("generating query XSD"); File xmlSchemaFile = new File(exportDir, dataEntity.getName() + ".xsd"); OutputStream xsdos = new FileOutputStream(xmlSchemaFile); PlasmaXSDHelper.INSTANCE.generate(query, dataEntity.getTargetNamespaceUri(), "ex", null, xsdos); xsdos.flush(); xsdos.close(); assert(query != null); log.info("defining XSD so new export-specific types are known"); FileInputStream xsdis = new FileInputStream(xmlSchemaFile); try { PlasmaXSDHelper.INSTANCE.define(xsdis, null); } catch (ConfigurationException e) { log.warn(e.getMessage()); } log.info("generating query XMI"); File xmiFile = new File(exportDir, dataEntity.getName() + ".xmi"); OutputStream xmios = new FileOutputStream(xmiFile); UMLModelAssembler assembler = new UMLModelAssembler(query, dataEntity.getTargetNamespaceUri(), "tns"); XMLOutputter outputer = new XMLOutputter(); outputer.output(assembler.getDocument(), xmios); xmios.flush(); xmios.close(); assert(query != null); SDODataAccessClient service = new SDODataAccessClient( new PojoDataAccessClient( DataAccessProviderName.valueOf(export.getProviderName()))); log.info("calling " + export.getProviderName() + " service"); DataGraph[] graphs = service.find(query); log.info("found " + graphs.length + " results"); XMLOptions options = new DefaultOptions( dataEntity.getTargetNamespaceUri(), null); if (exportFile == null) { for (int i = 0; i < graphs.length; i++) { File file = new File(exportDir, dataEntity.getName() + "-" + String.valueOf(i+1) + ".xml"); OutputStream xmlos = new FileOutputStream(file); XMLDocument doc = new CoreXMLDocument(graphs[i].getRootObject(), options); doc.setXMLDeclaration(true); PlasmaXMLHelper.INSTANCE.save(doc, xmlos, options); xmlos.flush(); xmlos.close(); } } else { // all results to a single file OutputStream xmlos = new FileOutputStream(exportFile); if (graphs.length > 1) { String start = "<" + dataEntity.getName() + " xmlns:" + options.getRootNamespacePrefix() + "=\"" + dataEntity.getTargetNamespaceUri() + "\"" + ">\n"; xmlos.write(start.getBytes()); } for (DataGraph graph : graphs) { XMLDocument doc = new CoreXMLDocument(graph.getRootObject(), options); doc.setXMLDeclaration(false); PlasmaXMLHelper.INSTANCE.save(doc, xmlos, options); } if (graphs.length > 1) { String end = "\n</" + dataEntity.getName() + ">"; xmlos.write(end.getBytes()); } xmlos.flush(); xmlos.close(); if (dataBinding != null) { // validate the XML we just produced against the given Schema/binding log.info("validating XML file: " + exportFile.getAbsolutePath()); try { InputStream xmlis = new FileInputStream(exportFile); dataBinding.validate(xmlis); } catch (Throwable t) { log.error(t.getMessage(), t); } } } } private Query unmarshalQuery(File queryFile) { Query query = null; try { PlasmaQueryDataBinding binding = new PlasmaQueryDataBinding( new DefaultValidationEventHandler()); FileInputStream is = new FileInputStream(queryFile); query = (Query)binding.validate(is); } catch (JAXBException e) { log.error(e.getMessage(), e); throw new IllegalArgumentException(e); } catch (SAXException e) { log.error(e.getMessage(), e); throw new IllegalArgumentException(e); } catch (FileNotFoundException e) { log.error(e.getMessage(), e); throw new IllegalArgumentException(e); } return query; } public static void main(String[] args) throws JAXBException, SAXException, IOException { new DataExtract(args); } }