| /** |
| * |
| * 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 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * 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.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.Component |
| import com.vaadin.ui.HorizontalLayout |
| import com.vaadin.ui.Label |
| import com.vaadin.ui.NativeButton |
| import com.vaadin.ui.Panel |
| import com.vaadin.ui.ProgressBar |
| import com.vaadin.ui.UI |
| import java.io.BufferedInputStream |
| import java.io.BufferedOutputStream |
| import java.io.File |
| import java.io.FileInputStream |
| import java.io.FileOutputStream |
| import java.io.IOException |
| import java.io.InputStream |
| import java.io.PrintWriter |
| 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.ArrayList |
| import java.util.Arrays |
| import java.util.Date |
| import java.util.HashMap |
| import java.util.List |
| import java.util.MissingResourceException |
| import java.util.Properties |
| import java.util.UUID |
| 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.TransformerConfigurationException |
| 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.apache.log4j.lf5.util.StreamUtils |
| 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.blob.service.BlobService |
| import org.eclipse.osbp.blob.service.BlobTypingAPI |
| import org.eclipse.osbp.datainterchange.api.DataInterchangeException |
| import org.eclipse.osbp.datainterchange.api.IDataInterchange |
| 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.LAnnotationTarget |
| 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.LFeature |
| 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.dsl.semantic.entity.LEntityReference |
| import org.eclipse.osbp.eventbroker.EventBrokerMsg |
| import org.eclipse.osbp.preferences.ProductConfiguration |
| import org.eclipse.osbp.runtime.common.event.EventDispatcherEvent |
| import org.eclipse.osbp.runtime.common.event.EventDispatcherEvent.EventDispatcherCommand |
| import org.eclipse.osbp.ui.api.datamart.IDataMart.EType |
| import org.eclipse.osbp.utils.entityhelper.DataType |
| 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.DataInterchangeBlobMapping |
| 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.DataInterchangeMapping |
| import org.eclipse.osbp.xtext.datainterchange.DataInterchangePackage |
| import org.eclipse.osbp.xtext.datainterchange.DataInterchangePredefinedExpression |
| import org.eclipse.osbp.xtext.datainterchange.DataInterchangeValueMapping |
| import org.eclipse.osbp.xtext.datainterchange.EntityManagerMode |
| import org.eclipse.osbp.xtext.datainterchange.common.WorkerThreadRunnable |
| import org.eclipse.osbp.xtext.entitymock.common.IEntityImportInitializationListener |
| 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.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 |
| import org.xml.sax.SAXException |
| import org.eclipse.osbp.xtext.datainterchange.DataInterchangeExportHide |
| import org.eclipse.osbp.xtext.datainterchange.DataInterchangeExportFilter |
| import org.eclipse.osbp.xtext.datainterchange.DataInterchangeGroup |
| import org.eclipse.xtext.common.types.JvmAnnotationReference |
| import org.eclipse.xtext.common.types.JvmGenericType |
| import org.eclipse.osbp.runtime.common.annotations.CreateBy |
| import org.eclipse.xtext.common.types.JvmAnnotationType |
| import org.eclipse.osbp.runtime.common.annotations.Dirty |
| import org.eclipse.osbp.runtime.common.annotations.UpdateAt |
| import org.eclipse.osbp.runtime.common.annotations.UpdateBy |
| import org.eclipse.osbp.runtime.common.annotations.CreateAt |
| |
| 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 pkg, IJvmDeclaredTypeAcceptor acceptor) { |
| pckgName = pkg.name |
| } |
| |
| 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") |
| |
| EcoreUtil.getAllContents(EObjectHelper.getSemanticElement(input), false).filter(typeof(DataInterchangePackage)).forEach[ |
| fsa.generatePathConfig(it) |
| ] |
| 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 generatePathConfig(IFileSystemAccess fsa, DataInterchangePackage dataInterchangePkg) { |
| var dir = new File('''«System.getProperty("user.home")»/.osbee''') |
| if(!dir.exists) { |
| dir.mkdir |
| } |
| dataInterchangePkg.groups.forEach[ |
| var file = new File('''«System.getProperty("user.home")»/.osbee/«it.name»Config.xml'''); |
| file.setWritable(true, false); |
| if(!file.exists) { |
| file.createNewFile |
| val properties = new Properties(); |
| it.datInts.forEach[ |
| properties.put('''«it.name»-«WorkerThreadRunnable.Direction.EXPORT.toString().toLowerCase()»'''.toString, it.getUrl) |
| properties.put('''«it.name»-«WorkerThreadRunnable.Direction.IMPORT.toString().toLowerCase()»'''.toString, it.getUrl) |
| ] |
| var fileOutput = new FileOutputStream(file); |
| properties.storeToXML(fileOutput, "dataInterchange file URLs"); |
| fileOutput.close |
| } |
| ] |
| } |
| |
| def getUrl(DataInterchange di) { |
| switch(di.fileEndpoint) { |
| DataInterchangeFileXML: |
| return (di.fileEndpoint as DataInterchangeFileXML).fileURL |
| DataInterchangeFileCSV: |
| return (di.fileEndpoint as DataInterchangeFileCSV).fileURL |
| DataInterchangeFileEDI: |
| return (di.fileEndpoint as DataInterchangeFileEDI).fileURL |
| } |
| } |
| |
| 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 DataResult() |
| 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 = <LEntityFeature>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 DataResult() |
| 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<LEntityFeature> fieldList, Document doc) { |
| var reader = doc.createElement("csv:reader") |
| var fields = doc.createAttribute("fields") |
| var fldList = <String>newArrayList |
| var mappingInterchanges = interchange.path.filter[it.hasAttributeMapping] |
| var lookupInterchanges = interchange.path.filter[it.hasReferenceLookup] |
| for(f:fieldList) { |
| if(f instanceof LEntityAttribute){ |
| if(mappingInterchanges.length > 0){ |
| for(mi:mappingInterchanges){ |
| for(mapping:mi.mappings){ |
| if(!fldList.contains(mapping.data) && f.name.equals(mapping.data)){ |
| fldList.add(f.toName) |
| } |
| } |
| } |
| }else{ |
| fldList.add(f.toName) |
| } |
| }else if(f instanceof LEntityReference && lookupInterchanges.length > 0){ |
| //add reference only if they are specified by lookup |
| for(li:lookupInterchanges){ |
| for(lup:li.lookup){ |
| if(!fldList.contains(lup.dataMap) && f.name.equals(lup.dataMap)){ |
| 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, DataInterchangeFile endPoint) { |
| 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('''«IF endPoint.encoding !== null»<#ftl encoding='«endPoint.encoding»'>«ENDIF»«IF endPoint.locale !== null»<#setting locale="«endPoint.locale»">«ENDIF»'''+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") !== null && !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, boolean byAttribute) { |
| 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") !== null && !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»/«IF byAttribute»@«ENDIF»«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, boolean byAttribute) { |
| 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") |
| var paramContent = paramValue |
| if(paramValue.equalsIgnoreCase("int")){ |
| paramContent = "Integer" |
| } |
| decoder.textContent = paramContent |
| daoValue.attributeNode = decoder |
| // mapping given? |
| if(dataMap !== null) { |
| var data = doc.createAttribute("data") |
| data.textContent = '''«elementMap»/«IF byAttribute»@«ENDIF»«dataMap»''' |
| daoValue.attributeNode = data |
| } |
| return daoParams |
| } |
| |
| def generateExportConfig(DataInterchange dataInterchange, Document doc, DataInterchangeFile endPoint, String delimiter, String quote) { |
| var substitutionMap = <String,String>newHashMap |
| var vectorMap = <String,String>newHashMap |
| var substitutionCount = 0 |
| var fieldList = <LEntityFeature>newArrayList |
| var String rootEntityName = null |
| var Document ftlDocument = null |
| var Element bean = null |
| var Element oldParent = null |
| var vector = "vector" |
| var depth = 0 |
| var LEntity previousEntity = null |
| // iterate through all path (bean) listed under `path` keyword |
| for(path : dataInterchange.path) { |
| // are there any mappings? |
| var mappingFound = hasAttributeMapping(path) |
| |
| if (rootEntityName === null && !path.isMarkLatestImport) { |
| rootEntityName = (path.entity as LAnnotationTarget).toName.toString |
| } |
| if (dataInterchange.fileEndpoint instanceof DataInterchangeFileXML) { |
| var currentKey = '''list«substitutionCount»''' |
| if(ftlDocument === null) { |
| ftlDocument = domImpl.createDocument(null, '''«IF dataInterchange.vectorName !== null»«dataInterchange.vectorName»«ELSE»vector«ENDIF»''', null) |
| } |
| vector = vectorMap.get(path.entity.toName) ?: vector |
| |
| substitutionMap.put(currentKey, '''«vector» as «path.entity.toName»''') |
| if(previousEntity !== null && !previousEntity.hasRelation(path.entity)){ |
| bean = createXmlBean(ftlDocument, oldParent, path.entity, path.format, currentKey, path, dataInterchange) |
| }else{ |
| oldParent = bean |
| bean = createXmlBean(ftlDocument, bean, path.entity, path.format, currentKey, path, dataInterchange) |
| depth = depth + 1 |
| } |
| substitutionCount = substitutionCount + 1 |
| previousEntity = path.entity |
| } |
| |
| for (f : path.entity.allFeatures) { |
| if(f instanceof LAttribute && !f.toMany && |
| path.getExportFilter !== null && |
| path.getExportFilter.hiddenproperties !== null && |
| !path.getExportFilter.hiddenproperties.empty && |
| !path.getExportFilter.hiddenproperties.toList.containsFeature(f)) { |
| if (!isInternal(f) && // don't export version |
| !path.isMarkLatestImport && |
| ((!(f as LEntityAttribute).id && !(f as LEntityAttribute).uuid) || (path.lookupKeys.empty && dataInterchange.mode != EntityManagerMode.PERSIST)) && |
| (!mappingFound || path.mappings.isMapped(f))) { |
| fieldList.add(f as LEntityAttribute) |
| } |
| } |
| if(f instanceof LReference && !f.toMany && path.lookupKeys.empty) { |
| fieldList.add(f as LEntityReference) |
| } |
| // if a feature is a 1-* reference, find if the referenced entity is also under this path. |
| if(f instanceof LReference && f.toMany && !path.isMarkLatestImport) { |
| var iter = dataInterchange.path.iterator |
| var next = iter.next |
| // find current entity |
| while (iter.hasNext && next.entity.toName != path.entity.toName) { |
| next = iter.next |
| } |
| while (iter.hasNext) { |
| // move to next entity |
| next = iter.next |
| if (next !== null && next.entity.toName == (f.type as LEntity).toName) { |
| vectorMap.put(next.entity.toName, '''«path.entity.toName».«f.name»''') |
| } |
| } |
| } |
| } |
| } |
| if(endPoint instanceof DataInterchangeFileCSV) { |
| createFreemarker(doc, createCsvTemplate(rootEntityName, fieldList, delimiter, quote, dataInterchange.path), endPoint) |
| } |
| if(endPoint instanceof DataInterchangeFileXML) { |
| createFreemarker(doc, createXmlTemplate(ftlDocument, substitutionMap, dataInterchange.path), endPoint) |
| } |
| } |
| |
| def boolean hasRelation(LEntity root, LEntity entity) { |
| var result = root.features.filter[it instanceof LReference && (it as LReference).type.equals(entity)] |
| return !result.empty |
| } |
| |
| def generateImportConfig(DataInterchange dataInterchange, List<LEntityFeature> fieldList, Document doc, DataInterchangeFile endPoint) { |
| var isFirst = true |
| var hasMarker = false |
| var autoMapping = "" |
| var byAttribute = false |
| if(endPoint instanceof DataInterchangeFileCSV) { |
| autoMapping = "/csv-set" |
| } else if(endPoint instanceof DataInterchangeFileXML) { |
| autoMapping = '''«IF dataInterchange.vectorName !== null»«dataInterchange.vectorName»«ELSE»vector«ENDIF»''' |
| byAttribute = endPoint.byAttribute |
| } |
| var depth = 0 |
| var oldMapping = "" |
| for(path : dataInterchange.path) { |
| var map = "" |
| if(path.elementMap === null) { |
| map = autoMapping |
| } else { |
| map = path.elementMap |
| } |
| if(path.isMarkLatestImport) { |
| hasMarker = true |
| } |
| var Element bean = null |
| if(!path.isMarkLatestImport && !hasMarker && isFirst) { |
| var rootBean = createBean(doc, path.entity.toName+"List", path.entity.fullyQualifiedName.toString, map, true) |
| createWiring(doc, rootBean, path.entity.toName, null, null) |
| isFirst = false |
| } |
| if(!path.isMarkLatestImport && endPoint instanceof DataInterchangeFileCSV) { |
| autoMapping = autoMapping + "/csv-record" |
| } |
| |
| if(endPoint instanceof DataInterchangeFileXML) { |
| if(depth < 1) { |
| autoMapping = '''«autoMapping»/«IF path.nodeName !== null»«path.nodeName»«ELSE»«path.entity.toName»«ENDIF»''' |
| oldMapping = autoMapping |
| depth++ |
| }else{ |
| autoMapping = '''«oldMapping»/«IF path.nodeName !== null»«path.nodeName»«ELSE»«path.entity.toName»«ENDIF»''' |
| } |
| } |
| if(path.elementMap === null) { |
| map = autoMapping |
| } else { |
| map = path.elementMap |
| } |
| bean = createBean(doc, path.entity.toName, path.entity.fullyQualifiedName.toString, map, false) |
| // if merge or remove - create a locator for id and version |
| if(dataInterchange.mode != EntityManagerMode.PERSIST) { |
| if(!path.lookupKeys.empty) { |
| createExpression(doc, bean, path.entity.idAttributeName, "?"+path.entity.toName+"Merger."+path.entity.idAttributeName) |
| if(path.entity.versionAttribute !== null) { |
| createExpression(doc, bean, path.entity.versionAttributeName, "?"+path.entity.toName+"Merger."+path.entity.versionAttributeName) |
| } |
| var locator = createDaoLocator(doc, null, path.entity.toName+"Merger", map, true, false) |
| createDaoQuery(doc, locator, path.queryKeys) |
| var pCnt = 0 |
| for(key:path.lookupKeys) { |
| createDaoParam(doc, locator, '''param«pCnt++»''', key.property.decoder, map, path.mappings.mapElement(key.property.name), byAttribute) |
| } |
| } |
| else if(path.entity.versionAttribute !== null) { |
| createExpression(doc, bean, path.entity.versionAttributeName, "?"+path.entity.toName+"Merger."+path.entity.versionAttributeName) |
| var locator = createDaoLocator(doc, null, path.entity.toName+"Merger", map, true, false) |
| createDaoQuery(doc, locator, path.queryVersion) |
| createDaoParam(doc, locator, '''param''', path.entity.primaryKeyAttribute.decoder, map, path.entity.idAttributeName, byAttribute) |
| } |
| } |
| // are there any mappings? |
| var mappingFound = hasAttributeMapping(path) |
| for (f : path.entity.allFeatures) { |
| switch f { |
| LAttribute: { |
| if (!f.toMany) { |
| // enable mapping for this field |
| // if not disposed and not latest marker and not id except no lookup keys given and mode is not persist |
| if (!isInternal(f) |
| && |
| ((!(f as LEntityAttribute).id && !(f as LEntityAttribute).uuid) |
| || |
| (path.lookupKeys.empty && dataInterchange.mode != EntityManagerMode.PERSIST)) |
| && |
| (!path.isMarkLatestImport || !path.latestProperty.toName.equals(f.toName)) |
| ) { |
| // add to the level's field list |
| if (!path.isMarkLatestImport) { |
| 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.toName.equals((expr as DataInterchangeEntityExpression).targetProperty.toName)) { |
| createExpression(doc, bean, f.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.toName.equals((expr as DataInterchangePredefinedExpression).targetProperty.toName)) { |
| if("UUID".equals((expr as DataInterchangePredefinedExpression).bean.literal)) { |
| createExpression(doc, bean, f.toName, "PUUID."+(expr as DataInterchangePredefinedExpression).beanType.getName) |
| } else { |
| createExpression(doc, bean, f.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.toName.equals(format.targetProperty.toName)) { |
| var value = createProperty(doc, bean, f.toName, f.decoder, dtType.getBasicType(f as LEntityAttribute)) |
| if(format.format !== null) { |
| createDecodeParam(doc, value, "format", format.format) |
| |
| if (endPoint.locale !== null) { |
| createDecodeParam(doc, value, "locale-language", endPoint.locale.split("_").get(0)) |
| if(endPoint.locale.split("_").size > 1) { |
| createDecodeParam(doc, value, "locale-country", endPoint.locale.split("_").get(1)) |
| } |
| } |
| |
| } |
| formatFound = true |
| } |
| } |
| // default for mapping purposes |
| if (!expressionFound && !formatFound) { |
| // create no property for unmapped marker entities |
| if (!(endPoint instanceof DataInterchangeFileCSV) || !path.isMarkLatestImport) { |
| // create no property if mapping is used and this attribute is unmapped |
| if(!mappingFound || path.mappings.isMapped(f)) { |
| var etype = dtType.getBasicType(f as LEntityAttribute) |
| |
| // add enum decoder |
| if(etype == EType.LENUM){ |
| var value = createProperty(doc, bean, f.toName, "Enum", etype) |
| createDecodeParam(doc, value, "enumType", f.type.toQualifiedName.toString) |
| |
| var enumsliterals = f.type.eContents; |
| for(literal : enumsliterals){ |
| val enumname = literal.fullyQualifiedName.lastSegment |
| // extra fileds |
| createDecodeParam(doc, value, enumsliterals.indexOf(literal).toString, enumname) |
| // mandatory fields |
| createDecodeParam(doc, value, enumname, enumname) |
| } |
| } |
| else{ |
| // add format decoder |
| var value = createProperty(doc, bean, f.toName, f.decoder, etype) |
| if (etype == EType.DATE) { |
| createDecodeParam(doc, value, "format", "yyyy-MM-dd'T'HH:mm:ss") |
| } else if((etype == EType.DOUBLE || etype == EType.FLOAT) && endPoint.locale !== null) { |
| createDecodeParam(doc, value, "format", "#.######") |
| if (endPoint.locale !== null) { |
| createDecodeParam(doc, value, "locale-language", endPoint.locale.split("_").get(0)) |
| if(endPoint.locale.split("_").size > 1) { |
| createDecodeParam(doc, value, "locale-country", endPoint.locale.split("_").get(1)) |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| // if mapping given |
| path.hasBlobMapping = false |
| for(mapping : path.mappings) { |
| if(f.name.equals(mapping.property.name)) { |
| addMapping(doc, bean, f.toName, mapping.data, byAttribute) |
| if(mapping instanceof DataInterchangeBlobMapping) { |
| path.hasBlobMapping = true |
| } |
| } |
| } |
| // default mapping for xml |
| if (!mappingFound && !path.isMarkLatestImport && endPoint instanceof DataInterchangeFileXML) { |
| addMapping(doc, bean, f.toName, f.toName, byAttribute) |
| } |
| } |
| } |
| } |
| // 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.toAdder(f.name).simpleName) |
| } |
| } |
| } else { |
| // many to one |
| if(path.lookup.isEmpty) { |
| fieldList.add(f as LEntityReference) |
| var field = (f as LEntityReference).type.primaryKeyAttribute |
| var etype = dtType.getBasicType(field) |
| |
| for(mapping : path.mappings) { |
| // might be buggy for xml |
| if(f.name.equals(mapping.property.name)) { |
| createProperty(doc, bean, f.toName, field.decoder, etype) |
| addMapping(doc, bean, f.toName, mapping.data, byAttribute) |
| } |
| } |
| |
| } else { |
| // 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)) { |
| if(endPoint instanceof DataInterchangeFileCSV){ |
| // the field will need to be included for header |
| fieldList.add(f as LEntityReference) |
| } |
| 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, byAttribute) |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| //for CSV file, if no mapping were found, simply map all attributes |
| if (!mappingFound && !path.isMarkLatestImport && endPoint instanceof DataInterchangeFileCSV) { |
| for(fld : fieldList) { |
| if(fld instanceof LEntityAttribute){ |
| addMapping(doc, bean, fld.toName, fld.toName, byAttribute) |
| } |
| } |
| } |
| } |
| } |
| |
| def boolean hasAnnotation(LFeature feature, Class<?> annotationType) { |
| for(anno:(feature as LEntityAttribute).annotationInfo.annotations) { |
| if (anno.annotation.annotationType.fullyQualifiedName.toString.equals(annotationType.name)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| def boolean isInternal(LFeature f) { |
| if("disposed".equals(f.toName)) { |
| return true |
| } |
| if((f as LEntityAttribute).version) { |
| return true |
| } |
| if(f.hasAnnotation(Dirty) || f.hasAnnotation(UpdateAt) || f.hasAnnotation(UpdateBy) || f.hasAnnotation(CreateAt) || f.hasAnnotation(CreateBy)) { |
| return true |
| } |
| return false |
| } |
| |
| protected def boolean hasAttributeMapping(DataInterchangeBean path) { |
| for(mapping : path.mappings) { |
| for (a : path.entity.allAttributes) { |
| if(a.name.equals(mapping.property.name)) { |
| return true |
| } |
| } |
| } |
| return false |
| } |
| |
| protected def boolean hasReferenceLookup(DataInterchangeBean path){ |
| for(lu : path.lookup) { |
| for(a : path.entity.getAllReferences) { |
| if(a.name.equals(lu.dataMap)){ |
| return true |
| } |
| } |
| } |
| return false |
| } |
| |
| protected def boolean hasReferenceExport(DataInterchangeBean path){ |
| for(expose : path.exportExposes) { |
| for(a : path.entity.getAllReferences) { |
| if(a.name.equals(expose.refEntity.name)){ |
| return true |
| } |
| } |
| } |
| return false |
| } |
| |
| def boolean isMapped(EList<DataInterchangeMapping> list, LFeature attribute) { |
| if(attribute instanceof LEntityAttribute) { |
| return !list.filter[it|it.property.name.equals(attribute.name)].empty |
| } |
| return false; |
| } |
| |
| def String mapElement(EList<DataInterchangeMapping> mappings, String propertyName) { |
| var element = (mappings.findFirst[it.property.name.equals(propertyName) && it instanceof DataInterchangeValueMapping] as DataInterchangeValueMapping)?.data |
| if(element === null) { |
| element = propertyName |
| } |
| return element |
| } |
| |
| def Element createXmlBean(Document doc, Element parent, LEntity entity, EList<DataInterchangeFormat> formats, String currentKey, DataInterchangeBean path, DataInterchange dataInterchange) { |
| // are there any mappings? |
| var mappingFound = hasAttributeMapping(path) |
| var bean = doc.createElement('''«IF path.nodeName !== null»«path.nodeName»«ELSE»«entity.toName»«ENDIF»''') |
| var pi = doc.createProcessingInstruction(currentKey, "") |
| if(parent === null) { |
| doc.documentElement.appendChild(pi) |
| doc.documentElement.appendChild(bean) |
| } else { |
| bean = doc.createElement('''«IF path.nodeName !== null»«path.nodeName»«ELSE»«entity.toName»«ENDIF»''') |
| parent.appendChild(pi) |
| parent.appendChild(bean) |
| } |
| for(p:entity.allAttributes) { |
| if(!isInternal(p) && // don't export version |
| ((!p.id && !p.uuid) || (path.lookupKeys.empty && dataInterchange.mode != EntityManagerMode.PERSIST)) && |
| (!mappingFound || path.mappings.isMapped(p))) { |
| 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.toName, p, format, "", true) |
| bean.appendChild(property) |
| } |
| } |
| for(e : path.exportExposes){ |
| var expose = e |
| var segments = <String>newArrayList() |
| segments.add(expose.refEntity.name) |
| while(expose.refProperty === null){ |
| expose = expose.subExpose |
| segments.add(expose.refEntity.name) |
| } |
| |
| var property = doc.createElement(expose.refProperty.toName) |
| var pathToProperty = segments.join(".") |
| |
| property.textContent = encodeFreemarker('''«entity.toName».«pathToProperty»''', expose.refProperty, null as DataInterchangeFormat, "", true); |
| 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 decoder(LEntityAttribute f) { |
| return getPrimitiveDataTypeName(f) |
| } |
| |
| 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, EList<DataInterchangeBean> path) { |
| var source = new DOMSource(doc) |
| var res = new DataResult() |
| transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); |
| transformer.transform(source, res) |
| var output = res.result |
| |
| // processing the template string for filtered information |
| for(f: path){ // for exclusion |
| if(f.getExportFilter !== null && f.getExportFilter.hiddenproperties !== null && !f.getExportFilter.hiddenproperties.empty){ |
| for(hiddenprop : f.getExportFilter.hiddenproperties){ |
| var attrname = hiddenprop.property.name |
| if(output.contains(attrname)){ |
| var targetstatement = output.substring(output.indexOf("<"+attrname+">${("+f.entity.name),output.indexOf("</"+attrname+">") + ("</"+attrname+">").length) |
| output = output.replace(targetstatement, "") |
| } |
| } |
| } |
| } |
| // cleaning whitespaces |
| var result = "" |
| for(f : output.split("\r")){ |
| if(!f.trim.isEmpty){ |
| result = result.concat(f) |
| } |
| } |
| // processing instructions are embedded in question marks - they must be replaced |
| for(k:substitutionMap.keySet) { |
| result = result.replaceFirst(k, '''#list «substitutionMap.get(k)»''') |
| } |
| for(l:substitutionMap.keySet) { |
| result = result.replaceFirst(l, '''/#list''') |
| } |
| return result.replace("<","<").replace(">",">").replace("<?","<").replace("?>",">")//.replace("</#","\n</#") |
| } |
| |
| def String createCsvTemplate(String rootEntityName, List<LEntityFeature> 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, false)) |
| fldList.add(field.toName) |
| } |
| var body = ''' |
| «fldList.join(delimiter)» |
| <#list vector as «rootEntityName»> |
| «tmpList.join(delimiter)» |
| </#list>''' |
| return body |
| } |
| |
| def String encodeFreemarker(String entityName, LEntityFeature field, EList<DataInterchangeBean> paths, String quote, boolean encodeHtml) { |
| 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, encodeHtml) |
| } |
| |
| def String encodeFreemarker(String entityName, LEntityFeature field, DataInterchangeFormat format, String quote, boolean encodeHtml) { |
| if(field instanceof LEntityAttribute) { |
| 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»?datetime?iso_local_ms_nz)!}''' |
| } |
| else if (etype == EType.STRING) { |
| return '''«quote»${(«entityName».«field.toName»«IF encodeHtml»?html«ENDIF»)!}«quote»''' |
| } |
| else { |
| return '''${(«entityName».«field.toName»)!}''' |
| } |
| } else { |
| var etype = dtType.getBasicType((field as LEntityReference).type.primaryKeyAttribute) |
| if (etype == EType.STRING) { |
| return '''«quote»${(«entityName».«field.toName».«(field as LEntityReference).type.primaryKeyAttribute.name»)!}«quote»''' |
| } else { |
| return '''${(«entityName».«field.toName».«(field as LEntityReference).type.primaryKeyAttribute.name»)!}''' |
| } |
| } |
| } |
| |
| /* 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 ")»''' |
| } |
| |
| def String queryKeys(DataInterchangeBean bean) { |
| var pCnt = 0 |
| var select = '''«bean.entity.toName» x''' |
| var whereList = <String>newArrayList |
| for(key:bean.lookupKeys) { |
| var qstr = '''x.«key.property.toName» = :param«pCnt++»''' |
| whereList.add(qstr) |
| } |
| return '''from «select» where «whereList.join(" and ")»''' |
| } |
| |
| def String queryVersion(DataInterchangeBean bean) { |
| var select = '''«bean.entity.toName» x''' |
| var qstr = '''x.«bean.entity.idAttributeName» = :param''' |
| return '''from «select» where «qstr»''' |
| } |
| |
| def boolean containsFeature(List<DataInterchangeExportHide> list, LEntityFeature f){ |
| for(exclude : list){ |
| if(exclude.property.equals(f)){ |
| return true |
| } |
| } |
| return false |
| } |
| |
| 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 |
| , IDataInterchange |
| , StreamSource |
| , URL |
| , URI |
| , InputStream |
| , StreamUtils |
| , MalformedURLException |
| , FileAlreadyExistsException |
| , URISyntaxException |
| , EntityManager |
| , 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 |
| , CriteriaBuilder |
| , CriteriaQuery |
| , Root |
| , TypedQuery |
| , JoinType |
| , Paths |
| , Path |
| , Files |
| , StandardOpenOption |
| , BufferedOutputStream |
| , BufferedInputStream |
| , UI |
| , Pair |
| , IEntityImportInitializationListener |
| , ConstraintViolationException |
| , ConstraintViolation |
| , EventDispatcherEvent |
| , EventDispatcherCommand |
| , DataInterchangeException |
| , TransformerConfigurationException |
| , SAXException |
| , IOException |
| , UUID |
| , IOException |
| , File |
| , FileInputStream |
| , Properties |
| , ProductConfiguration |
| , PrintWriter |
| , BlobService |
| , BlobTypingAPI |
| , Component |
| , Panel |
| , Paths |
| , Date |
| ) |
| super.createAppendable(context, importManager, config) |
| } |
| } |