| /** |
| * |
| * Copyright (c) 2011, 2016 - Loetz GmbH&Co.KG (69115 Heidelberg, Germany) |
| * |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Christophe Loetz (Loetz GmbH&Co.KG) - initial implementation |
| * |
| * |
| * This copyright notice shows up in the generated Java code |
| * |
| */ |
| |
| package org.eclipse.osbp.xtext.datainterchange.jvmmodel |
| |
| import com.google.common.collect.Lists |
| import com.vaadin.shared.ui.label.ContentMode |
| import com.vaadin.ui.Button |
| import com.vaadin.ui.Button.ClickEvent |
| import com.vaadin.ui.Button.ClickListener |
| import com.vaadin.ui.HorizontalLayout |
| import com.vaadin.ui.Label |
| import com.vaadin.ui.NativeButton |
| import com.vaadin.ui.ProgressBar |
| import com.vaadin.ui.UI |
| import java.io.BufferedOutputStream |
| import java.io.ByteArrayInputStream |
| import java.io.IOException |
| import java.io.InputStream |
| import java.io.StringReader |
| import java.io.StringWriter |
| import java.net.MalformedURLException |
| import java.net.URI |
| import java.net.URISyntaxException |
| import java.net.URL |
| import java.nio.file.FileAlreadyExistsException |
| import java.nio.file.Files |
| import java.nio.file.Path |
| import java.nio.file.Paths |
| import java.nio.file.StandardOpenOption |
| import java.text.MessageFormat |
| import java.util.Arrays |
| import java.util.HashMap |
| import java.util.List |
| import java.util.MissingResourceException |
| import java.util.concurrent.Executors |
| import java.util.concurrent.TimeUnit |
| import javax.inject.Inject |
| import javax.persistence.EntityManager |
| import javax.persistence.EntityTransaction |
| import javax.persistence.TypedQuery |
| import javax.persistence.criteria.CriteriaBuilder |
| import javax.persistence.criteria.CriteriaQuery |
| import javax.persistence.criteria.JoinType |
| import javax.persistence.criteria.Root |
| import javax.validation.ConstraintViolation |
| import javax.validation.ConstraintViolationException |
| import javax.xml.parsers.DocumentBuilderFactory |
| import javax.xml.transform.OutputKeys |
| import javax.xml.transform.Transformer |
| import javax.xml.transform.TransformerFactory |
| import javax.xml.transform.dom.DOMSource |
| import javax.xml.transform.stream.StreamResult |
| import javax.xml.transform.stream.StreamSource |
| import org.apache.commons.lang.StringEscapeUtils |
| import org.eclipse.e4.core.di.extensions.EventUtils |
| import org.eclipse.e4.core.services.events.IEventBroker |
| import org.eclipse.emf.common.util.EList |
| import org.eclipse.emf.ecore.EObject |
| import org.eclipse.emf.ecore.resource.Resource |
| import org.eclipse.emf.ecore.util.EcoreUtil |
| import org.eclipse.osbp.dsl.entity.xtext.extensions.EntityTypesBuilder |
| import org.eclipse.osbp.dsl.entity.xtext.extensions.ModelExtensions |
| import org.eclipse.osbp.dsl.semantic.common.types.LAttribute |
| import org.eclipse.osbp.dsl.semantic.common.types.LDataType |
| import org.eclipse.osbp.dsl.semantic.common.types.LReference |
| import org.eclipse.osbp.dsl.semantic.entity.LEntity |
| import org.eclipse.osbp.dsl.semantic.entity.LEntityAttribute |
| import org.eclipse.osbp.dsl.semantic.entity.LEntityFeature |
| import org.eclipse.osbp.eventbroker.EventBrokerMsg |
| import org.eclipse.osbp.utils.entityhelper.DataType |
| import org.eclipse.osbp.utils.entitymock.IEntityImportInitializationListener |
| import org.eclipse.osbp.xtext.addons.EObjectHelper |
| import org.eclipse.osbp.xtext.basic.generator.BasicDslGeneratorUtils |
| import org.eclipse.osbp.xtext.datainterchange.DataInterchange |
| import org.eclipse.osbp.xtext.datainterchange.DataInterchangeBean |
| import org.eclipse.osbp.xtext.datainterchange.DataInterchangeEntityExpression |
| import org.eclipse.osbp.xtext.datainterchange.DataInterchangeFile |
| import org.eclipse.osbp.xtext.datainterchange.DataInterchangeFileCSV |
| import org.eclipse.osbp.xtext.datainterchange.DataInterchangeFileEDI |
| import org.eclipse.osbp.xtext.datainterchange.DataInterchangeFileXML |
| import org.eclipse.osbp.xtext.datainterchange.DataInterchangeFormat |
| import org.eclipse.osbp.xtext.datainterchange.DataInterchangeLookup |
| import org.eclipse.osbp.xtext.datainterchange.DataInterchangePackage |
| import org.eclipse.osbp.xtext.datainterchange.DataInterchangePredefinedExpression |
| import org.eclipse.osbp.xtext.datainterchange.common.WorkerThreadRunnable |
| import org.eclipse.osbp.xtext.i18n.DSLOutputConfigurationProvider |
| import org.eclipse.osbp.xtext.i18n.I18NModelGenerator |
| import org.eclipse.persistence.config.PersistenceUnitProperties |
| import org.eclipse.persistence.config.PessimisticLock |
| import org.eclipse.persistence.config.QueryHints |
| import org.eclipse.xtext.generator.IFileSystemAccess |
| import org.eclipse.xtext.generator.IOutputConfigurationProvider |
| import org.eclipse.xtext.naming.IQualifiedNameProvider |
| import org.eclipse.xtext.naming.QualifiedName |
| import org.eclipse.xtext.xbase.compiler.GeneratorConfig |
| import org.eclipse.xtext.xbase.compiler.ImportManager |
| import org.eclipse.xtext.xbase.jvmmodel.IJvmDeclaredTypeAcceptor |
| import org.eclipse.osbp.ui.api.datamart.IDataMart.EType |
| import org.milyn.Smooks |
| import org.milyn.SmooksFactory |
| import org.milyn.SmooksOSGIFactory |
| import org.milyn.container.ExecutionContext |
| import org.milyn.event.report.HtmlReportGenerator |
| import org.milyn.event.types.ElementPresentEvent |
| import org.milyn.event.types.FilterLifecycleEvent |
| import org.milyn.event.types.FilterLifecycleEvent.EventType |
| import org.milyn.io.StreamUtils |
| import org.milyn.javabean.binding.xml.XMLBinding |
| import org.milyn.payload.JavaResult |
| import org.milyn.payload.JavaSource |
| import org.milyn.payload.StringResult |
| import org.milyn.persistence.util.PersistenceUtil |
| import org.milyn.scribe.adapter.jpa.EntityManagerRegister |
| import org.osgi.framework.Bundle |
| import org.osgi.framework.BundleContext |
| import org.osgi.framework.FrameworkUtil |
| import org.osgi.service.event.Event |
| import org.osgi.service.event.EventHandler |
| import org.slf4j.Logger |
| import org.slf4j.LoggerFactory |
| import org.w3c.dom.Document |
| import org.w3c.dom.Element |
| |
| class ParameterValue { |
| var public HashMap<String,String> modifiers = <String,String>newHashMap() |
| var public String value |
| } |
| |
| class DataDSLModelGenerator extends I18NModelGenerator { |
| @Inject extension IQualifiedNameProvider |
| @Inject extension ModelExtensions |
| @Inject extension EntityTypesBuilder |
| @Inject extension IOutputConfigurationProvider outputConfig |
| @Inject extension BasicDslGeneratorUtils |
| |
| @Inject |
| @Extension |
| private DataType dtType; |
| |
| val static protected CAPTION__REPFIX_I18NKEY_EXPORT = "export" |
| val static protected CAPTION__REPFIX_I18NKEY_IMPORT = "import" |
| |
| var public static String pckgName = null |
| val DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); |
| val transformerFactory = TransformerFactory.newInstance() |
| var Transformer transformer = null |
| var db = dbf.newDocumentBuilder() |
| var domImpl = db.DOMImplementation |
| |
| def String generateKey(String name, QualifiedName packageName) { |
| var pattern = "(\\W)" |
| if (name != null) { |
| var newName = name.replaceAll(pattern ,"_").toLowerCase |
| System.out.println(newName) |
| if (packageName != null) { |
| return packageName.toString.concat(".").concat(newName) |
| } |
| else { |
| return newName |
| } |
| } |
| return null |
| } |
| |
| def void generatePckgName(DataInterchangePackage dip, IJvmDeclaredTypeAcceptor acceptor) { |
| pckgName = dip.getName |
| } |
| |
| override doGenerate(Resource input, IFileSystemAccess fsa) { |
| addTranslatables('''«CAPTION__REPFIX_I18NKEY_EXPORT»,«CAPTION__REPFIX_I18NKEY_IMPORT»''') |
| |
| // identation for pretty xml output |
| transformerFactory.setAttribute("indent-number", 4); |
| transformer = transformerFactory.newTransformer() |
| transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no"); |
| transformer.setOutputProperty(OutputKeys.INDENT, "yes") |
| transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8") |
| transformer.setOutputProperty(OutputKeys.STANDALONE, "yes") |
| transformer.setOutputProperty(OutputKeys.MEDIA_TYPE, "text/xml") |
| |
| var configList = Lists.newArrayList(outputConfig.outputConfigurations) |
| var outputDirectory = "" |
| for(config:configList) { |
| if(config.name.equals(DSLOutputConfigurationProvider.SMOOKS_OUTPUT_ONCE)) { |
| outputDirectory = config.outputDirectory |
| } |
| } |
| EcoreUtil.getAllContents(EObjectHelper.getSemanticElement(input), false).filter(typeof(DataInterchange)).forEach[ |
| // create all smooks config files |
| fsa.generateImportConfigStub(it) |
| fsa.generateExportConfigStub(it) |
| ] |
| super.doGenerate(input, fsa) |
| } |
| |
| def void generateExportConfigStub(IFileSystemAccess fsa, DataInterchange dataInterchange) { |
| var body = "" |
| dbf.namespaceAware = true |
| var document = domImpl.createDocument("http://www.milyn.org/xsd/smooks-1.1.xsd", "smooks-resource-list", null) |
| |
| var config = document.createElement("resource-config") |
| var selector = document.createAttribute("selector") |
| selector.textContent = "global-parameters" |
| config.attributeNode = selector; |
| var pEl = document.createElement("param"); |
| var name = document.createAttribute("name") |
| name.textContent = "stream.filter.type" |
| pEl.attributeNode = name |
| var value = document.createTextNode("SAX") |
| pEl.appendChild(value) |
| config.appendChild(pEl) |
| document.documentElement.appendChild(config) |
| |
| var cartridges = <String,String>newHashMap() |
| cartridges.put("xmlns:jb", "http://www.milyn.org/xsd/smooks/javabean-1.4.xsd") |
| switch (dataInterchange.fileEndpoint) { |
| DataInterchangeFileCSV: { |
| var delimiter = "" |
| var quote = "" |
| cartridges.put("xmlns:ftl", "http://www.milyn.org/xsd/smooks/freemarker-1.1.xsd") |
| var csv = dataInterchange.fileEndpoint as DataInterchangeFileCSV |
| if(csv.delimiter != null) { |
| delimiter = StringEscapeUtils.unescapeHtml(csv.delimiter) |
| } |
| if(csv.quoteCharacter != null) { |
| quote = StringEscapeUtils.unescapeHtml(csv.quoteCharacter) |
| } |
| dataInterchange.generateExportConfig(document, dataInterchange.fileEndpoint, delimiter, quote) |
| } |
| DataInterchangeFileXML: { |
| cartridges.put("xmlns:ftl", "http://www.milyn.org/xsd/smooks/freemarker-1.1.xsd") |
| dataInterchange.generateExportConfig(document, dataInterchange.fileEndpoint, null, null) |
| } |
| DataInterchangeFileEDI: { |
| } |
| } |
| for(cdg:cartridges.keySet) { |
| document.documentElement.setAttributeNS("http://www.w3.org/2000/xmlns/", cdg, cartridges.get(cdg)) |
| } |
| |
| var source = new DOMSource(document) |
| var res = new StringResult() |
| transformer.transform(source, res) |
| body = res.result |
| fsa.generateFile('''«dataInterchange.name»-«WorkerThreadRunnable.Direction.EXPORT.toString().toLowerCase()».xml''', DSLOutputConfigurationProvider.SMOOKS_OUTPUT_ONCE, body) |
| } |
| |
| def void generateImportConfigStub(IFileSystemAccess fsa, DataInterchange dataInterchange) { |
| var body = "" |
| dbf.namespaceAware = true |
| var db = dbf.newDocumentBuilder() |
| var domImpl = db.DOMImplementation |
| var document = domImpl.createDocument("http://www.milyn.org/xsd/smooks-1.1.xsd", "smooks-resource-list", null) |
| |
| var fieldList = <LEntityAttribute>newArrayList() |
| var cartridges = <String,String>newHashMap() |
| var parameters = <String,ParameterValue>newHashMap() |
| // for the meaning of cartridges see: http://www.smooks.org/mediawiki/index.php?title=V1.5:Smooks_v1.5_User_Guidecartridges |
| cartridges.put("xmlns:jb", "http://www.milyn.org/xsd/smooks/javabean-1.2.xsd") |
| cartridges.put("xmlns:dao", "http://www.milyn.org/xsd/smooks/persistence-1.2.xsd") |
| var pval = new ParameterValue |
| pval.value = "SAX" |
| parameters.put("stream.filter.type", pval) |
| // the smooks.visitor.sort=false removes NPE when using dao:lookup according to: |
| // http://milyn.996300.n3.nabble.com/jira-Created-MILYN-265-Add-support-for-Producer-Consumer-based-sorting-of-Visitor-logic-td3387.html |
| pval = new ParameterValue |
| pval.value = "false" |
| parameters.put("smooks.visitors.sort", pval) |
| |
| switch (dataInterchange.fileEndpoint) { |
| DataInterchangeFileXML: { |
| // set input type and active filename |
| pval = new ParameterValue |
| pval.value = "input.xml" |
| parameters.put("inputType", pval) |
| pval = new ParameterValue |
| pval.value = (dataInterchange.fileEndpoint as DataInterchangeFileXML).fileURL |
| pval.modifiers.put("type", "input.type.actived") |
| parameters.put("input.xml", pval) |
| dataInterchange.generateImportConfig(fieldList, document, dataInterchange.fileEndpoint) |
| (dataInterchange.fileEndpoint as DataInterchangeFileXML).input(dataInterchange, document) |
| } |
| DataInterchangeFileCSV: { |
| cartridges.put("xmlns:csv", "http://www.milyn.org/xsd/smooks/csv-1.2.xsd") |
| // set input type and active filename |
| pval = new ParameterValue |
| pval.value = "input.csv" |
| parameters.put("inputType", pval) |
| pval = new ParameterValue |
| pval.value = (dataInterchange.fileEndpoint as DataInterchangeFileCSV).fileURL |
| pval.modifiers.put("type", "input.type.actived") |
| parameters.put("input.csv", pval) |
| dataInterchange.generateImportConfig(fieldList, document, dataInterchange.fileEndpoint) |
| (dataInterchange.fileEndpoint as DataInterchangeFileCSV).input(dataInterchange, fieldList, document) |
| } |
| DataInterchangeFileEDI: { |
| cartridges.put("xmlns:edi", "http://www.milyn.org/xsd/smooks/edi-1.2.xsd") |
| // set input type and active filename |
| pval = new ParameterValue |
| pval.value = "input.edi" |
| parameters.put("inputType", pval) |
| pval = new ParameterValue |
| pval.value = (dataInterchange.fileEndpoint as DataInterchangeFileEDI).fileURL |
| pval.modifiers.put("type", "input.type.actived") |
| parameters.put("input.edi", pval) |
| dataInterchange.generateImportConfig(fieldList, document, dataInterchange.fileEndpoint) |
| (dataInterchange.fileEndpoint as DataInterchangeFileEDI).input(dataInterchange, document) |
| } |
| } |
| for(cdg:cartridges.keySet) { |
| document.documentElement.setAttributeNS("http://www.w3.org/2000/xmlns/", cdg, cartridges.get(cdg)) |
| } |
| var params = document.createElement("params") |
| for(para:parameters.keySet) { |
| var pEl = document.createElement("param"); |
| var name = document.createAttribute("name") |
| name.textContent = para |
| pEl.attributeNode = name |
| var value = document.createTextNode(parameters.get(para).value) |
| pEl.appendChild(value) |
| for(mod:parameters.get(para).modifiers.keySet) { |
| var pAt = document.createAttribute(mod) |
| pAt.textContent = parameters.get(para).modifiers.get(mod) |
| pEl.attributeNode = pAt |
| } |
| params.appendChild(pEl) |
| } |
| document.documentElement.appendChild(params) |
| var source = new DOMSource(document) |
| var res = new StringResult() |
| transformer.transform(source, res) |
| body = res.result |
| fsa.generateFile('''«dataInterchange.name»-«WorkerThreadRunnable.Direction.IMPORT.toString().toLowerCase()».xml''', DSLOutputConfigurationProvider.SMOOKS_OUTPUT_ONCE, body) |
| } |
| |
| def input(DataInterchangeFileXML xml, DataInterchange interchange, Document doc) { |
| } |
| |
| def input(DataInterchangeFileCSV csv, DataInterchange interchange, List<LEntityAttribute> fieldList, Document doc) { |
| var reader = doc.createElement("csv:reader") |
| var fields = doc.createAttribute("fields") |
| var fldList = <String>newArrayList |
| for(f:fieldList) { |
| fldList.add(f.toName) |
| } |
| fields.textContent = fldList.join(",") |
| reader.attributeNode = fields |
| |
| if(csv.delimiter != null) { |
| var sep = doc.createAttribute("separator") |
| sep.textContent = csv.delimiter |
| reader.attributeNode = sep |
| } |
| |
| if(csv.quoteCharacter != null) { |
| var quote = doc.createAttribute("quote") |
| quote.textContent = StringEscapeUtils.unescapeXml(csv.quoteCharacter) |
| reader.attributeNode = quote; |
| } |
| |
| var indent = doc.createAttribute("indent") |
| indent.textContent = csv.indent.booleanValue.toString |
| reader.attributeNode = indent |
| |
| var skip = doc.createAttribute("skipLines") |
| skip.textContent = csv.skipLines.toString |
| reader.attributeNode = skip |
| |
| doc.documentElement.appendChild(reader) |
| } |
| |
| def input(DataInterchangeFileEDI edi, DataInterchange interchange, Document doc) { |
| var reader = doc.createElement("edi:reader") |
| var mapping = doc.createAttribute("mappingModel") |
| mapping.textContent = edi.mappingModel |
| reader.attributeNode = mapping |
| |
| var validate = doc.createAttribute("validate") |
| validate.textContent = edi.validate.booleanValue.toString |
| reader.attributeNode = validate |
| |
| doc.documentElement.appendChild(reader) |
| } |
| |
| def createFreemarker(Document doc, String templateString) { |
| var freemarker = doc.createElement("ftl:freemarker") |
| var apply = doc.createAttribute("applyOnElement") |
| apply.textContent = "#document" |
| freemarker.attributeNode = apply |
| |
| doc.documentElement.appendChild(freemarker) |
| var template = doc.createElement("ftl:template") |
| var tplName = doc.createCDATASection(templateString.replaceAll("\r","")); |
| template.appendChild(tplName) |
| freemarker.appendChild(template) |
| } |
| |
| def Element createBean(Document doc, String beanIdName, String className, String elementMap, boolean isList) { |
| var bean = doc.createElement("jb:bean") |
| doc.documentElement.appendChild(bean) |
| var beanId = doc.createAttribute("beanId") |
| beanId.textContent = beanIdName |
| bean.attributeNode = beanId |
| var clazz = doc.createAttribute("class") |
| clazz.textContent = '''«className»«IF isList»[]«ENDIF»''' |
| bean.attributeNode = clazz |
| // is mapping given? |
| if(elementMap != null) { |
| var create = doc.createAttribute("createOnElement") |
| create.textContent = elementMap |
| bean.attributeNode = create |
| } |
| return bean |
| } |
| |
| def Element createProperty(Document doc, Element parent, String propertyName, String decoderName, EType type) { |
| var Element value = null |
| // try to find a value element, or create a new one |
| var node = parent.firstChild |
| while(node != null && (!node.nodeName.equals("jb:value") || !node.attributes.getNamedItem("property").nodeValue.equals(propertyName))) { |
| node = node.nextSibling |
| } |
| if(node == null) { |
| value = doc.createElement("jb:value") |
| parent.appendChild(value) |
| } else { |
| value = node as Element |
| } |
| |
| var property = doc.createAttribute("property") |
| property.textContent = propertyName |
| value.attributeNode = property |
| if(decoderName != null) { |
| var decoder = doc.createAttribute("decoder") |
| decoder.textContent = decoderName |
| value.attributeNode = decoder |
| } |
| if (type == EType.DATE) { |
| var defaultValue = doc.createAttribute("default") |
| defaultValue.textContent = "null" |
| value.attributeNode = defaultValue |
| } |
| return value |
| } |
| |
| def addMapping(Document doc, Element parent, String propertyName, String dataName) { |
| var elementMap = "" |
| var attr = parent.attributes.getNamedItem("createOnElement") |
| if (attr != null) { |
| elementMap = attr.textContent |
| } |
| var Element value = null |
| // try to find a value element, or create a new one |
| var node = parent.firstChild |
| while(node != null && node.hasAttributes && (!node.nodeName.equals("jb:value") || !node.attributes.getNamedItem("property").nodeValue.equals(propertyName))) { |
| node = node.nextSibling |
| } |
| if(node == null) { |
| value = doc.createElement("jb:value") |
| parent.appendChild(value) |
| } else { |
| value = node as Element |
| } |
| var data = doc.createAttribute("data") |
| data.textContent = elementMap+"/"+dataName |
| value.attributeNode = data |
| } |
| |
| def Element createDecodeParam(Document doc, Element parent, String paramName, String paramValue) { |
| var param = doc.createElement("jb:decodeParam") |
| parent.appendChild(param) |
| var name = doc.createAttribute("name") |
| name.textContent = paramName |
| param.attributeNode = name |
| var form = doc.createTextNode(paramValue) |
| param.appendChild(form) |
| return param |
| } |
| |
| def Element createWiring(Document doc, Element parent, String beanIdRefName, String propertyName, String setterName) { |
| var value = doc.createElement("jb:wiring") |
| parent.appendChild(value) |
| var beanIdRef = doc.createAttribute("beanIdRef") |
| beanIdRef.textContent = beanIdRefName |
| value.attributeNode = beanIdRef |
| if(propertyName != null) { |
| var property = doc.createAttribute("property") |
| property.textContent = propertyName |
| value.attributeNode = property |
| } |
| if(setterName != null) { |
| var setter = doc.createAttribute("setterMethod") |
| setter.textContent = setterName |
| value.attributeNode = setter |
| } |
| return value |
| } |
| |
| def Element createExpression(Document doc, Element parent, String propertyName, String propertyValue) { |
| var expression = doc.createElement("jb:expression") |
| parent.appendChild(expression) |
| var property = doc.createAttribute("property") |
| property.textContent = propertyName |
| expression.attributeNode = property |
| var propNode = doc.createTextNode(propertyValue) |
| expression.appendChild(propNode) |
| return expression |
| } |
| |
| def Element createDaoLocator(Document doc, Element parent, String beanIdName, String elementMap, boolean allowNoResult, boolean allowNonuniqueResult) { |
| var locator = doc.createElement("dao:locator") |
| if (parent == null) { |
| doc.documentElement.appendChild(locator) |
| } else { |
| parent.appendChild(locator) |
| } |
| var beanId = doc.createAttribute("beanId") |
| beanId.textContent = beanIdName |
| locator.attributeNode = beanId |
| // mapping given? |
| if(elementMap != null) { |
| var lookupOnElement = doc.createAttribute("lookupOnElement") |
| lookupOnElement.textContent = elementMap |
| locator.attributeNode = lookupOnElement |
| } |
| |
| if(!allowNoResult) { |
| var onNoResult = doc.createAttribute("onNoResult") |
| onNoResult.textContent = "EXCEPTION" |
| locator.attributeNode = onNoResult |
| } |
| var uniqueResult = doc.createAttribute("uniqueResult") |
| uniqueResult.textContent = (!allowNonuniqueResult).booleanValue.toString |
| locator.attributeNode = uniqueResult |
| return locator |
| } |
| |
| def Element createDaoQuery(Document doc, Element parent, String query) { |
| var daoQuery = doc.createElement("dao:query") |
| parent.appendChild(daoQuery) |
| var queryText = doc.createTextNode(query) |
| daoQuery.appendChild(queryText) |
| return daoQuery |
| } |
| |
| def Element createDaoParam(Document doc, Element parent, String paramName, String paramValue, String elementMap, String dataMap) { |
| var Element daoParams = null |
| var node = parent.firstChild |
| while(node != null && !node.nodeName.equals("dao:params")) { |
| node = node.nextSibling |
| } |
| if(node == null) { |
| daoParams = doc.createElement("dao:params") |
| parent.appendChild(daoParams) |
| } else { |
| daoParams = node as Element |
| } |
| var daoValue = doc.createElement("dao:value") |
| daoParams.appendChild(daoValue) |
| var param = doc.createAttribute("name") |
| param.textContent = paramName |
| daoValue.attributeNode = param |
| var decoder = doc.createAttribute("decoder") |
| decoder.textContent = paramValue |
| daoValue.attributeNode = decoder |
| // mapping given? |
| if(dataMap != null) { |
| var data = doc.createAttribute("data") |
| data.textContent = elementMap+"/"+dataMap |
| daoValue.attributeNode = data |
| } |
| return daoParams |
| } |
| |
| def generateExportConfig(DataInterchange dataInterchange, Document doc, DataInterchangeFile endPoint, String delimiter, String quote) { |
| var substitutionMap = <String,String>newHashMap |
| var substitutionCount = 0 |
| var fieldList = <LEntityAttribute>newArrayList |
| var String rootEntityName = null |
| var Document ftlDocument = null |
| var Element bean = null |
| var vector = "vector" |
| for(path : dataInterchange.path) { |
| if (rootEntityName == null) { |
| rootEntityName = path.entity.name.toString |
| } |
| if (dataInterchange.fileEndpoint instanceof DataInterchangeFileXML) { |
| var currentKey = '''list«substitutionCount»''' |
| if(ftlDocument == null) { |
| ftlDocument = domImpl.createDocument(null, "vector", null) |
| } |
| substitutionMap.put(currentKey, '''«vector» as «path.entity.name»''') |
| bean = createXmlBean(ftlDocument, bean, path.entity, path.format, currentKey) |
| substitutionCount = substitutionCount + 1 |
| } |
| for (f : path.entity.features) { |
| if(f instanceof LAttribute && !f.toMany) { |
| if ((!"disposed".equals((f as LEntityFeature).toName) && (!"id".equals((f as LEntityFeature).toName)))) { |
| fieldList.add(f as LEntityAttribute) |
| } |
| } |
| if(f instanceof LReference && f.toMany) { |
| var iter = dataInterchange.path.iterator |
| var next = iter.next |
| // find this entity |
| while (iter.hasNext && !next.entity.toName.equals(path.entity.toName)) { |
| next = iter.next |
| } |
| while (iter.hasNext) { |
| // move to next entity |
| next = iter.next |
| if (next != null && next.entity.toName.equals((f.type as LEntity).toName)) { |
| vector = '''«path.entity.name».«(f as LEntityFeature).name»''' |
| } |
| } |
| } |
| } |
| } |
| if(endPoint instanceof DataInterchangeFileCSV) { |
| createFreemarker(doc, createCsvTemplate(rootEntityName, fieldList, delimiter, quote, dataInterchange.path)) |
| } |
| if(endPoint instanceof DataInterchangeFileXML) { |
| createFreemarker(doc, createXmlTemplate(ftlDocument, substitutionMap)) |
| } |
| } |
| |
| def generateImportConfig(DataInterchange dataInterchange, List<LEntityAttribute> fieldList, Document doc, DataInterchangeFile endPoint) { |
| var autoMapping = "" |
| if(endPoint instanceof DataInterchangeFileCSV) { |
| autoMapping = "/csv-set" |
| } else if(endPoint instanceof DataInterchangeFileXML) { |
| autoMapping = "vector" |
| } |
| for(path : dataInterchange.path) { |
| var map = "" |
| if(path.elementMap == null) { |
| map = autoMapping |
| } else { |
| map = path.elementMap |
| } |
| var Element bean = null |
| if(path.recordList) { |
| var rootBean = createBean(doc, path.entity.toName+"List", path.entity.fullyQualifiedName.toString, map, true) |
| createWiring(doc, rootBean, path.entity.toName, null, null) |
| if(endPoint instanceof DataInterchangeFileCSV) { |
| autoMapping = autoMapping + "/csv-record" |
| } else if(endPoint instanceof DataInterchangeFileXML) { |
| autoMapping = autoMapping + "/" + path.entity.toName |
| } |
| if(path.elementMap == null) { |
| map = autoMapping |
| } else { |
| map = path.elementMap |
| } |
| bean = createBean(doc, path.entity.toName, path.entity.fullyQualifiedName.toString, map, false) |
| } else { |
| if(endPoint instanceof DataInterchangeFileXML) { |
| autoMapping = autoMapping + "/" + path.entity.toName |
| } |
| if(path.elementMap == null) { |
| map = autoMapping |
| } else { |
| map = path.elementMap |
| } |
| bean = createBean(doc, path.entity.toName, path.entity.fullyQualifiedName.toString, map, false) |
| } |
| var mappingFound = false |
| for (f : path.entity.features) { |
| switch f { |
| LAttribute: { |
| if (!f.toMany) { |
| // enable mapping for this field, but first try special cases... |
| if ((!"disposed".equals((f as LEntityFeature).toName) && (!"id".equals((f as LEntityFeature).toName) && (!path.markLatest || !path.latestProperty.toName.equals((f as LEntityFeature).toName))))) { |
| // add to the level's field list |
| if (path.recordList || path.recordElement) { |
| fieldList.add(f as LEntityAttribute) |
| } |
| var expressionFound = false |
| // scan expressions for this field |
| for (expr : path.expression) { |
| switch(expr) { |
| DataInterchangeEntityExpression: { |
| // is there an entity expression for this attribute ? |
| if ((f as LEntityFeature).toName.equals((expr as DataInterchangeEntityExpression).targetProperty.toName)) { |
| createExpression(doc, bean, (f as LEntityFeature).toName, (expr as DataInterchangeEntityExpression).entity.toName+"."+(expr as DataInterchangeEntityExpression).property.toName) |
| expressionFound = true |
| } |
| } |
| DataInterchangePredefinedExpression: { |
| // is there an predefined expression modeled for this attribute ? |
| if ((f as LEntityFeature).toName.equals((expr as DataInterchangePredefinedExpression).targetProperty.toName)) { |
| if("UUID".equals((expr as DataInterchangePredefinedExpression).bean.literal)) { |
| createExpression(doc, bean, (f as LEntityFeature).toName, "PUUID."+(expr as DataInterchangePredefinedExpression).beanType.getName) |
| } else { |
| createExpression(doc, bean, (f as LEntityFeature).toName, "PTIME."+(expr as DataInterchangePredefinedExpression).bean.getName+(expr as DataInterchangePredefinedExpression).beanType.getName) |
| } |
| expressionFound = true |
| } |
| } |
| } |
| } |
| // scan formats for this field |
| var formatFound = false |
| for (format : path.format) { |
| // is there a format modeled for this attribute ? |
| if ((f as LEntityFeature).toName.equals(format.targetProperty.toName)) { |
| var value = createProperty(doc, bean, (f as LEntityFeature).toName, (f as LEntityFeature).decoder, dtType.getBasicType(f as LEntityAttribute)) |
| if(format.format != null) { |
| createDecodeParam(doc, value, "format", format.format) |
| if (format.locale != null) { |
| createDecodeParam(doc, value, "locale-language", format.locale.split("_").get(0)) |
| if(format.locale.split("_").size > 1) { |
| createDecodeParam(doc, value, "locale-country", format.locale.split("_").get(1)) |
| } |
| } |
| } |
| formatFound = true |
| } |
| } |
| // scan lookup for this field - import only |
| var lookupFound = false |
| for (lookup : path.lookup) { |
| // entity and property must match |
| if ((f as LEntityFeature).toName.equals(lookup.targetProperty.toName)) { |
| var value = createWiring(doc, bean, (f.type as LEntity).toName, (f as LReference).name, null) |
| var locator = createDaoLocator(doc, value, (f.type as LEntity).toName, lookup.elementMap, lookup.allowNoResult, lookup.allowNonuniqueResult) |
| var daoQuery = createDaoQuery(doc, locator, (f.type as LEntity).query(lookup)) |
| createDaoParam(doc, daoQuery, "param", (f as LEntityFeature).type.name.toFirstUpper, lookup.elementMap, lookup.dataMap) |
| } |
| } |
| // default for mapping purposes |
| if (!expressionFound && !formatFound && !lookupFound) { |
| // add format decoder |
| var etype = dtType.getBasicType(f as LEntityAttribute) |
| var value = createProperty(doc, bean, (f as LEntityFeature).toName, (f as LEntityFeature).decoder, etype) |
| if (etype == EType.DATE) { |
| createDecodeParam(doc, value, "format", "yyyy-MM-dd") |
| } |
| } |
| // if mapping given |
| for(mapping : path.mappings) { |
| if(f.name.equals(mapping.property.name)) { |
| addMapping(doc, bean, (f as LEntityFeature).toName, mapping.data) |
| mappingFound = true |
| } |
| } |
| // if recordElement given |
| if (!mappingFound && !fieldList.isEmpty) { |
| if (path.recordList || path.recordElement) { |
| for(fld : fieldList) { |
| addMapping(doc, bean, fld.toName, fld.toName) |
| } |
| } |
| } |
| // default mapping for xml |
| if (!mappingFound && endPoint instanceof DataInterchangeFileXML) { |
| addMapping(doc, bean, (f as LEntityFeature).toName, (f as LEntityFeature).toName) |
| } |
| } |
| } |
| } |
| // check relations for modeled lookup |
| LReference: { |
| if (f.toMany) { |
| // one to many |
| // mapped automatically |
| var iter = dataInterchange.path.iterator |
| var next = iter.next |
| // find this entity |
| while (iter.hasNext && !next.entity.toName.equals(path.entity.toName)) { |
| next = iter.next |
| } |
| while (iter.hasNext) { |
| // move to next entity |
| next = iter.next |
| if (next != null && next.entity.toName.equals((f.type as LEntity).toName)) { |
| createWiring(doc, bean, (f.type as LEntity).toName, null, (f as LEntityFeature).toAdder((f as LEntityFeature).name).simpleName) |
| } |
| } |
| } else { |
| // many to one |
| // generate possible lookups for this many to one relationship |
| for (lookup : path.lookup) { |
| // entity and property must match |
| if (lookup.targetProperty.toName.equals((f as LReference).name)) { |
| createWiring(doc, bean, (f.type as LEntity).toName, (f as LReference).name, null) |
| var locator = createDaoLocator(doc, null, (f.type as LEntity).toName, lookup.elementMap, lookup.allowNoResult, lookup.allowNonuniqueResult) |
| createDaoQuery(doc, locator, (f.type as LEntity).query(lookup)) |
| createDaoParam(doc, locator, "param", lookup.queryProperty.type.name.toFirstUpper, lookup.elementMap, lookup.dataMap) |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| def Element createXmlBean(Document doc, Element parent, LEntity entity, EList<DataInterchangeFormat> formats, String currentKey) { |
| var bean = doc.createElement(entity.name) |
| var pi = doc.createProcessingInstruction(currentKey, "") |
| if(parent == null) { |
| doc.documentElement.appendChild(pi) |
| doc.documentElement.appendChild(bean) |
| } else { |
| bean = doc.createElement(entity.name) |
| parent.appendChild(pi) |
| parent.appendChild(bean) |
| } |
| for(p:entity.allAttributes) { |
| if ((!"disposed".equals(p.toName) && (!"id".equals(p.toName)))) { |
| var format = null as DataInterchangeFormat |
| for (step : formats) { |
| // is there a format modeled for this attribute ? |
| if ((p as LEntityFeature).toName.equals(step.targetProperty.toName)) { |
| if (step.format != null) { |
| format = step |
| } |
| } |
| } |
| var property = doc.createElement(p.toName) |
| property.textContent = encodeFreemarker(entity.name, p, format, "") |
| bean.appendChild(property) |
| } |
| } |
| var pa = doc.createProcessingInstruction(currentKey, "") |
| if(parent == null) { |
| doc.documentElement.appendChild(pa) |
| } else { |
| parent.appendChild(pa) |
| } |
| return bean |
| } |
| |
| def String decoder(LEntityFeature f) { |
| return getPrimitiveDataTypeName(f as LEntityAttribute) |
| } |
| |
| def String getPrimitiveDataTypeName(LEntityAttribute attribute) { |
| var eType = dtType.getBasicType(attribute) |
| var String typeName = null |
| if (eType == EType.DATE) { |
| typeName = "Date" |
| } |
| else if (attribute.type != null && (attribute.type instanceof LDataType) && (attribute.type as LDataType).jvmTypeReference != null) { |
| typeName = (attribute.type as LDataType).jvmTypeReference.simpleName |
| } else { |
| typeName = attribute.type.name |
| } |
| if ("int".equals(typeName)) { |
| typeName = "Integer" |
| } |
| return typeName.toFirstUpper |
| } |
| // <ftl:freemarker applyOnElement="org.eclipse.osbp.foodmart.entities.Mregion"> |
| // <ftl:template> |
| // <!--<#list vector as Mregion> |
| //<Mregion> |
| // <sales_city>${Mregion.sales_city}</sales_city> |
| // <#list Mregion.stores as Mstore> |
| // <store_type>${Mstore.store_type}</store_type> |
| // </#list> |
| //</Mregion> |
| //</#list> |
| //--> |
| // </ftl:template> |
| // </ftl:freemarker> |
| |
| def String createXmlTemplate(Document doc, HashMap<String,String> substitutionMap) { |
| var source = new DOMSource(doc) |
| var res = new StringResult() |
| transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); |
| transformer.transform(source, res) |
| var output = res.result |
| // processing instructions are embedded in question marks - they must be replaced |
| for(l:substitutionMap.keySet) { |
| output = output.replaceFirst(l, '''#list «substitutionMap.get(l)»''') |
| } |
| for(l:substitutionMap.keySet) { |
| output = output.replaceFirst(l, '''/#list''') |
| } |
| return output.replace("<","<").replace(">",">").replace("<?","<").replace("?>",">")//.replace("</#","\n</#") |
| } |
| |
| def String createCsvTemplate(String rootEntityName, List<LEntityAttribute> fieldList, String delimiter, String quote, EList<DataInterchangeBean> paths) { |
| var tmpList = <String>newArrayList() |
| var fldList = <String>newArrayList |
| for(field:fieldList) { |
| tmpList.add(encodeFreemarker(rootEntityName, field, paths, quote)) |
| fldList.add(field.toName) |
| } |
| var body = '''«fldList.join(delimiter)» |
| <#list vector as «rootEntityName»> |
| «tmpList.join(delimiter)» |
| </#list>''' |
| return body |
| } |
| |
| def String encodeFreemarker(String entityName, LEntityAttribute field, EList<DataInterchangeBean> paths, String quote) { |
| var format = null as DataInterchangeFormat |
| val entity = field.eContainer as LEntity |
| for (path : paths) { |
| if (path.entity.equals(entity)) { |
| for (step : path.format) { |
| // is there a format modeled for this attribute ? |
| if (field.toName.equals(step.targetProperty.toName)) { |
| if (step.format != null) { |
| format = step |
| } |
| } |
| } |
| } |
| } |
| return encodeFreemarker(entityName, field, format, quote) |
| } |
| |
| def String encodeFreemarker(String entityName, LEntityAttribute field, DataInterchangeFormat format, String quote) { |
| var etype = dtType.getBasicType(field) |
| if (etype == EType.BOOLEAN) { |
| return '''${(«entityName».«field.toName»?c)!}''' |
| } |
| else if (format != null) { |
| return '''${(«entityName».«field.toName»?string["«format.format»"])!}''' |
| } |
| else if (etype == EType.DATE) { |
| return '''${(«entityName».«field.toName»?date)!}''' |
| } |
| else if (etype == EType.STRING) { |
| return '''«quote»${(«entityName».«field.toName»)!}«quote»''' |
| } |
| else { |
| return '''${(«entityName».«field.toName»)!}''' |
| } |
| } |
| |
| /* create a multistage left joined query to climb up along the one to many relations until import marker */ |
| def String query(LEntity entity, DataInterchangeLookup lookup) { |
| var aliasCnt = 0 |
| var select = '''«entity.toName» x«aliasCnt»''' |
| var joinList = <String>newArrayList |
| var whereList = <String>newArrayList |
| var qstr = '''x«aliasCnt».«lookup.queryProperty.toName» = :param''' |
| whereList.add(qstr) |
| if (lookup.markerPath != null) { |
| for(markerEntity:lookup.markerPath.path) { |
| aliasCnt = aliasCnt + 1 |
| if (markerEntity.markLatest) { |
| qstr = '''x«aliasCnt».«markerEntity.markerProperty.toName» = 1''' |
| whereList.add(qstr) |
| } |
| for(ff:entity.features) { |
| if (ff instanceof LReference && !ff.toMany) { |
| if (markerEntity.markerEntity.toName.equals((ff.type as LEntity).toName)) { |
| qstr = '''x«aliasCnt-1».«ff.toName» x«aliasCnt»''' |
| joinList.add(qstr) |
| } |
| } |
| } |
| } |
| } |
| return '''from «select»«IF joinList.size>0» left join «ENDIF»«joinList.join(" left join ")» where «whereList.join(" and ")»''' |
| } |
| |
| override createAppendable(EObject context, ImportManager importManager, GeneratorConfig config) { |
| // required to initialize the needed builder to avoid deprecated methods |
| builder = context.eResource |
| // --------- |
| addImportFor(importManager, _typeReferenceBuilder |
| , FrameworkUtil |
| , SmooksOSGIFactory |
| , SmooksFactory |
| , Smooks |
| , HtmlReportGenerator |
| , ExecutionContext |
| , JavaResult |
| , XMLBinding |
| , StreamSource |
| , ByteArrayInputStream |
| , URL |
| , URI |
| , InputStream |
| , StreamUtils |
| , MalformedURLException |
| , IOException |
| , FileAlreadyExistsException |
| , URISyntaxException |
| , EntityManager |
| , PersistenceUtil |
| , EntityManagerRegister |
| , EntityTransaction |
| , Logger |
| , LoggerFactory |
| , Label |
| , Button |
| , NativeButton |
| , ClickListener |
| , ClickEvent |
| , ContentMode |
| , PersistenceUnitProperties |
| , HorizontalLayout |
| , ProgressBar |
| , IEventBroker |
| , WorkerThreadRunnable |
| , HashMap |
| , Executors |
| , TimeUnit |
| , QueryHints |
| , PessimisticLock |
| , MissingResourceException |
| , MessageFormat |
| , EventHandler |
| , Event |
| , EventUtils |
| , EventBrokerMsg |
| , Bundle |
| , BundleContext |
| , List |
| , Arrays |
| , StringWriter |
| , StringReader |
| , OutputKeys |
| , StreamResult |
| , JavaSource |
| , CriteriaBuilder |
| , CriteriaQuery |
| , Root |
| , TypedQuery |
| , JoinType |
| , Paths |
| , Path |
| , Files |
| , StandardOpenOption |
| , BufferedOutputStream |
| , FilterLifecycleEvent |
| , ElementPresentEvent |
| , EventType |
| , UI |
| , Pair |
| , IEntityImportInitializationListener |
| , ConstraintViolationException |
| , ConstraintViolation |
| ) |
| super.createAppendable(context, importManager, config) |
| } |
| } |