| /** |
| * |
| * 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.Arrays |
| import java.util.Date |
| import java.util.HashMap |
| import java.util.List |
| import java.util.Map |
| 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.Join |
| import javax.persistence.criteria.JoinType |
| import javax.persistence.criteria.ListJoin |
| import javax.persistence.criteria.Root |
| import javax.persistence.metamodel.EntityType |
| import javax.persistence.metamodel.Metamodel |
| 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.core.resources.ResourcesPlugin |
| import org.eclipse.core.runtime.IPath |
| 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.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.LBean |
| import org.eclipse.osbp.dsl.semantic.entity.LBeanAttribute |
| import org.eclipse.osbp.dsl.semantic.entity.LEntity |
| import org.eclipse.osbp.dsl.semantic.entity.LEntityAttribute |
| 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.annotations.CreateAt |
| import org.eclipse.osbp.runtime.common.annotations.CreateBy |
| 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.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.DataInterchangeExportHide |
| 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.DataInterchangeFileFixed |
| import org.eclipse.osbp.xtext.datainterchange.DataInterchangeFileXML |
| import org.eclipse.osbp.xtext.datainterchange.DataInterchangeFixedColumnMapping |
| import org.eclipse.osbp.xtext.datainterchange.DataInterchangeFormat |
| import org.eclipse.osbp.xtext.datainterchange.DataInterchangeLookup |
| import org.eclipse.osbp.xtext.datainterchange.DataInterchangeLookupFilterCondition |
| import org.eclipse.osbp.xtext.datainterchange.DataInterchangeLookupFilterOperandProperty |
| import org.eclipse.osbp.xtext.datainterchange.DataInterchangeLookupFilterOperandString |
| import org.eclipse.osbp.xtext.datainterchange.DataInterchangeLookupMapping |
| 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.DataInterchangePropertyMapping |
| import org.eclipse.osbp.xtext.datainterchange.DataInterchangeSkipMapping |
| 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.EcoreUtil2 |
| import org.eclipse.xtext.generator.IFileSystemAccess |
| 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 |
| |
| 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 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.produceAppropiateInterchangeURL(null)) |
| properties.put('''«it.name»-«WorkerThreadRunnable.Direction.IMPORT.toString().toLowerCase()»'''.toString, it.produceAppropiateInterchangeURL(null)) |
| if(it.fileEndpoint instanceof DataInterchangeFileCSV && it.path !== null && it.path.size > 1){ |
| var firstBean = it.path.get(0) |
| for(bean : it.path){ |
| if(bean !== firstBean){ |
| var dataInterChangeFileName = if(bean.fileName !== null && !bean.fileName.empty) bean.fileName else it.getDataInterchangeFileName.replace(".csv", "_"+firstBean.entity.name+"_"+bean.entity.name+".csv") |
| properties.put('''«it.name»_«bean.entity.name»-«WorkerThreadRunnable.Direction.EXPORT.toString().toLowerCase()»'''.toString, it.produceAppropiateInterchangeURL(dataInterChangeFileName)) |
| properties.put('''«it.name»_«bean.entity.name»-«WorkerThreadRunnable.Direction.IMPORT.toString().toLowerCase()»'''.toString, it.produceAppropiateInterchangeURL(dataInterChangeFileName)) |
| } |
| } |
| } |
| ] |
| var fileOutput = new FileOutputStream(file); |
| properties.storeToXML(fileOutput, "dataInterchange file URLs"); |
| fileOutput.close |
| } |
| else { |
| var fileInput = new FileInputStream(file); |
| val properties = new Properties(); |
| properties.loadFromXML(fileInput) |
| fileInput.close |
| it.datInts.forEach[ |
| properties.put('''«it.name»-«WorkerThreadRunnable.Direction.EXPORT.toString().toLowerCase()»'''.toString, it.produceAppropiateInterchangeURL(null)) |
| properties.put('''«it.name»-«WorkerThreadRunnable.Direction.IMPORT.toString().toLowerCase()»'''.toString, it.produceAppropiateInterchangeURL(null)) |
| if(it.fileEndpoint instanceof DataInterchangeFileCSV && it.path !== null && it.path.size > 1){ |
| var firstBean = it.path.get(0) |
| for(bean : it.path){ |
| var dataInterChangeFileName = if(bean.fileName !== null && !bean.fileName.empty) bean.fileName else it.getDataInterchangeFileName.replace(".csv", "_"+firstBean.entity.name+"_"+bean.entity.name+".csv") |
| if(bean !== firstBean){ |
| properties.put('''«it.name»_«bean.entity.name»-«WorkerThreadRunnable.Direction.EXPORT.toString().toLowerCase()»'''.toString, it.produceAppropiateInterchangeURL(dataInterChangeFileName)) |
| properties.put('''«it.name»_«bean.entity.name»-«WorkerThreadRunnable.Direction.IMPORT.toString().toLowerCase()»'''.toString, it.produceAppropiateInterchangeURL(dataInterChangeFileName)) |
| } |
| } |
| } |
| ] |
| var fileOutput = new FileOutputStream(file); |
| properties.storeToXML(fileOutput, "dataInterchange file URLs"); |
| fileOutput.close |
| } |
| ] |
| } |
| |
| /** |
| * Generates the right file url for both absolute and relative paths. |
| */ |
| def String produceAppropiateInterchangeURL(DataInterchange interchange, String subfilename) { |
| var givenurl = interchange.fileURL |
| var filename = if(subfilename !== null && !subfilename.empty) subfilename else interchange.dataInterchangeFileName |
| var directory = interchange.getDataInterchangeDirectoryUrlPath |
| |
| try { |
| var url = new URL(givenurl) |
| if(url.protocol.equals("file")){ |
| // for relative path |
| if(!Paths.get(directory).absolute){ |
| var projectname = interchange.eResource.URI.segment(1) |
| var location = findProjectFileOrFolderLocation(projectname, directory, false) |
| givenurl = location.append(filename).toString |
| } |
| } |
| } |
| catch (Exception e1) { |
| if(e1.getMessage().startsWith("unknown protocol") || e1.getMessage().startsWith("no protocol")) { |
| try{ |
| // check for relative path |
| if(!Paths.get(directory).absolute){ |
| var projectname = interchange.eResource.URI.segment(1) |
| var location = findProjectFileOrFolderLocation(projectname, directory, false) |
| givenurl = location.append(filename).toString |
| } |
| } |
| catch (Exception e2) {} |
| } |
| } |
| // if the path is absolute or from another protocol like http, ftp ... |
| return givenurl |
| } |
| |
| /** |
| * Returns the path of the given file name or directory name. |
| */ |
| def IPath findProjectFileOrFolderLocation(String projectname, String fname, boolean isFile) { |
| if(projectname !== null && !projectname.empty && fname !== null && !fname.empty){ |
| var project = ResourcesPlugin.workspace.root.getProject(projectname); |
| if(isFile){ |
| return project.getFile(fname).location |
| } |
| return project.getFolder(fname).location |
| } |
| return null |
| } |
| |
| |
| def String getFileURL(DataInterchange dataInterchange) { |
| switch(dataInterchange.fileEndpoint) { |
| DataInterchangeFileXML: return (dataInterchange.fileEndpoint as DataInterchangeFileXML).fileURL |
| DataInterchangeFileCSV: return (dataInterchange.fileEndpoint as DataInterchangeFileCSV).fileURL |
| DataInterchangeFileEDI: return (dataInterchange.fileEndpoint as DataInterchangeFileEDI).fileURL |
| DataInterchangeFileFixed: return (dataInterchange.fileEndpoint as DataInterchangeFileFixed).fileURL |
| } |
| return "" |
| } |
| |
| /** |
| * Gives the file path of a data interchange unit without its file name. |
| */ |
| def String getDataInterchangeDirectoryUrlPath(DataInterchange interchange){ |
| var modelurl = "" |
| if(interchange !== null){ |
| var index = interchange.fileURL.lastIndexOf("/") |
| if( index !== -1) { |
| modelurl = interchange.fileURL.substring(0, index + 1) |
| }else{ |
| index = interchange.fileURL.lastIndexOf("\\") |
| if(index !== -1){ |
| modelurl = interchange.fileURL.substring(0, index + 1) |
| } |
| } |
| } |
| return modelurl |
| } |
| |
| /** |
| * Gives the file name of a data interchange unit. |
| */ |
| def String getDataInterchangeFileName(DataInterchange interchange){ |
| var filename = "" |
| if(interchange !== null){ |
| var index = interchange.fileURL.lastIndexOf("/") |
| if( index !== -1) { |
| filename = interchange.fileURL.substring(index + 1, interchange.fileURL.length) |
| }else{ |
| index = interchange.fileURL.lastIndexOf("\\") |
| if(index !== -1){ |
| filename = interchange.fileURL.substring(index + 1, interchange.fileURL.length) |
| } |
| } |
| } |
| return filename |
| } |
| |
| 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 |
| DataInterchangeFileFixed: |
| return (di.fileEndpoint as DataInterchangeFileFixed).fileURL |
| } |
| } |
| |
| def Document createEmptyDocumentForExport(){ |
| 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) |
| |
| return document |
| } |
| |
| def void generateExportConfigStub(IFileSystemAccess fsa, DataInterchange dataInterchange) { |
| dbf.namespaceAware = true |
| var Document document = null |
| var csvDocs = <String,Document>newHashMap() |
| |
| 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) |
| } |
| if(dataInterchange.path !== null && dataInterchange.path.size >= 1){ |
| dataInterchange.generateCSVExportConfig(csvDocs, dataInterchange.fileEndpoint, delimiter, quote) |
| } |
| } |
| DataInterchangeFileXML: { |
| if(document === null){document = createEmptyDocumentForExport} |
| cartridges.put("xmlns:ftl", "http://www.milyn.org/xsd/smooks/freemarker-1.1.xsd") |
| dataInterchange.generateExportConfig(document, dataInterchange.fileEndpoint, null, null) |
| } |
| DataInterchangeFileEDI: { |
| if(document === null){document = createEmptyDocumentForExport} |
| } |
| DataInterchangeFileFixed: { |
| if(document === null){document = createEmptyDocumentForExport} |
| cartridges.put("xmlns:ftl", "http://www.milyn.org/xsd/smooks/freemarker-1.1.xsd") |
| dataInterchange.generateExportConfig(document, dataInterchange.fileEndpoint, null, null) |
| } |
| } |
| |
| if(dataInterchange.fileEndpoint instanceof DataInterchangeFileCSV){ |
| |
| var firstEntityName = dataInterchange.path.get(0).entity.name |
| for(entityName : csvDocs.keySet){ |
| var doc = csvDocs.get(entityName) |
| |
| for(cdg:cartridges.keySet) { |
| doc.documentElement.setAttributeNS("http://www.w3.org/2000/xmlns/", cdg, cartridges.get(cdg)) |
| } |
| |
| var source = new DOMSource(doc) |
| var res = new DataResult() |
| transformer.transform(source, res) |
| var newBody = res.result |
| |
| if(entityName === firstEntityName){ |
| fsa.generateFile('''«dataInterchange.name»-«WorkerThreadRunnable.Direction.EXPORT.toString().toLowerCase()».xml''', DSLOutputConfigurationProvider.SMOOKS_OUTPUT_ONCE, newBody) |
| } |
| else{ |
| fsa.generateFile('''«dataInterchange.name»_«entityName»-«WorkerThreadRunnable.Direction.EXPORT.toString().toLowerCase()».xml''', DSLOutputConfigurationProvider.SMOOKS_OUTPUT_ONCE, newBody) |
| } |
| } |
| |
| }else{ |
| |
| 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) |
| var body = res.result |
| |
| fsa.generateFile('''«dataInterchange.name»-«WorkerThreadRunnable.Direction.EXPORT.toString().toLowerCase()».xml''', DSLOutputConfigurationProvider.SMOOKS_OUTPUT_ONCE, body) |
| } |
| |
| } |
| |
| def generateCSVExportConfig(DataInterchange dataInterchange, HashMap<String, Document> csvDocs, DataInterchangeFile endPoint, String delimiter, String quote) { |
| for(bean : dataInterchange.path) { |
| var vectorMap = <String,String>newHashMap |
| var fieldList = <LFeature>newArrayList |
| var String rootEntityName = null |
| var entityName = (bean.entity as LAnnotationTarget).toName.toString |
| |
| if (rootEntityName === null && !bean.isMarkLatestImport) { |
| rootEntityName = (bean.entity as LAnnotationTarget).toName.toString |
| } |
| var doc = createEmptyDocumentForExport |
| var LAttribute prevAttr = null |
| // create bean attributes if and only if mappings are defined |
| if(hasAttributeMapping(bean)){ |
| for (f : bean.entity.allFeatures) { |
| |
| if(useFeature(f, bean, dataInterchange)) { |
| if(f instanceof LAttribute && f.type instanceof LBean) { |
| prevAttr = f as LAttribute |
| } else { |
| var format = null as DataInterchangeFormat |
| for (step : bean.format) { |
| // is there a format modeled for this attribute ? |
| if ((f as LFeature).toName.equals(step.targetProperty.toName)) { |
| if (step.format !== null) { |
| format = step |
| } |
| } |
| } |
| createExportAttribute(dataInterchange, bean, f, fieldList, vectorMap) |
| // property.textContent = encodeFreemarker(bean.entity.toName, f, format, "", true, -1, prevAttr?.toName, null) |
| } |
| } |
| |
| // if(f instanceof LEntityAttribute && f.type instanceof LBean) { |
| // var beanAttr = (f as LEntityAttribute).type as LBean |
| // for(ba : beanAttr.allFeatures) { |
| // createExportAttribute(dataInterchange, bean, ba, fieldList, vectorMap) |
| // } |
| // } |
| } |
| } |
| createFreemarker(doc, createCsvTemplate(bean, fieldList, delimiter, quote, dataInterchange.path), endPoint) |
| csvDocs.put(entityName, doc) |
| } |
| } |
| |
| def void generateImportConfigStub(IFileSystemAccess fsa, DataInterchange dataInterchange) { |
| var location = "Workspace://"+EcoreUtil2.getPlatformResourceOrNormalizedURI(dataInterchange).segmentsList.get(1)+"/" |
| 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 = <LFeature>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.makePath(location) |
| 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.makePath(location) |
| 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.makePath(location) |
| 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) |
| } |
| DataInterchangeFileFixed: { |
| cartridges.put("xmlns:fl", "http://www.milyn.org/xsd/smooks/fixed-length-1.3.xsd") |
| pval = new ParameterValue |
| pval.value = "input.txt" |
| parameters.put("inputType", pval) |
| pval = new ParameterValue |
| pval.value = (dataInterchange.fileEndpoint as DataInterchangeFileFixed).fileURL.makePath(location) |
| pval.modifiers.put("type", "input.type.actived") |
| parameters.put("input.txt", pval) |
| dataInterchange.generateImportConfig(fieldList, document, dataInterchange.fileEndpoint) |
| (dataInterchange.fileEndpoint as DataInterchangeFileFixed).input(dataInterchange, fieldList, 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 String makePath(String fileURL, String location) { |
| var path = Paths.get(fileURL) |
| if(path.absolute) { |
| return fileURL |
| } else { |
| return location + fileURL |
| } |
| } |
| |
| def input(DataInterchangeFileXML xml, DataInterchange interchange, Document doc) { |
| } |
| |
| def input(DataInterchangeFileCSV csv, DataInterchange interchange, List<LFeature> 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] |
| if(mappingInterchanges.empty){ |
| for(f:fieldList) { |
| if(f instanceof LEntityAttribute || f instanceof LBeanAttribute){ |
| fldList.add(f.toName) |
| }else if(f instanceof LEntityReference && lookupInterchanges.length > 0){ |
| // add reference only if they are specified by lookup |
| // as a consequence they are located at the end of the list |
| for(li:lookupInterchanges){ |
| for(lup:li.lookup){ |
| if(!fldList.contains(lup.dataMap) && f.name.equals(lup.dataMap)){ |
| fldList.add(f.toName) |
| } |
| } |
| } |
| } |
| } |
| } else { |
| for(mi:mappingInterchanges){ |
| for(mapping:mi.mappings){ |
| if(mapping instanceof DataInterchangePropertyMapping) { |
| if(!(mapping instanceof DataInterchangeBlobMapping)) { |
| fldList.add(mapping.data) |
| } |
| } else { |
| if(mapping instanceof DataInterchangeLookupMapping) { |
| fldList.add(mapping.lookupReference.toName) |
| } |
| if(mapping instanceof DataInterchangeSkipMapping) { |
| fldList.add(mapping.name) |
| } |
| } |
| } |
| } |
| } |
| |
| 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 input(DataInterchangeFileFixed fixed, DataInterchange interchange, List<LFeature> fieldList, Document doc) { |
| var reader = doc.createElement("fl:reader") |
| var fields = doc.createAttribute("fields") |
| var fldList = <String>newArrayList |
| var iter = interchange.path.iterator |
| if(iter.hasNext) { |
| var path = iter.next |
| for(map:path.mappings) { |
| var column = map as DataInterchangeFixedColumnMapping |
| fldList.add(column.createFixedLengthField) |
| } |
| fields.textContent = fldList.join(",") |
| reader.attributeNode = fields |
| } |
| doc.documentElement.appendChild(reader) |
| } |
| |
| def String createFixedLengthField(DataInterchangeFixedColumnMapping f) { |
| var body = '''«f.property.toName»[«f.length»]''' |
| var isFirst = true |
| if(f.trim) { |
| body = '''«body»«IF isFirst»?«ELSE».«ENDIF»trim''' |
| isFirst = false |
| } |
| if(f.leftTrim) { |
| body = '''«body»«IF isFirst»?«ELSE».«ENDIF»left_trim''' |
| isFirst = false |
| } |
| if(f.rightTrim) { |
| body = '''«body»«IF isFirst»?«ELSE».«ENDIF»right_trim''' |
| isFirst = false |
| } |
| if(f.upperCase) { |
| body = '''«body»«IF isFirst»?«ELSE».«ENDIF»upper_case''' |
| isFirst = false |
| } |
| if(f.lowerCase) { |
| body = '''«body»«IF isFirst»?«ELSE».«ENDIF»lower_case''' |
| isFirst = false |
| } |
| if(f.capFirst) { |
| body = '''«body»«IF isFirst»?«ELSE».«ENDIF»cap_first''' |
| isFirst = false |
| } |
| if(f.uncapFirst) { |
| body = '''«body»«IF isFirst»?«ELSE».«ENDIF»uncap_first''' |
| isFirst = false |
| } |
| if(f.capitalize) { |
| body = '''«body»«IF isFirst»?«ELSE».«ENDIF»capitalize''' |
| isFirst = false |
| } |
| return body |
| } |
| |
| 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 |
| var done = false |
| while(node !== null && (!node.nodeName.equals("jb:value") || (node.attributes.getNamedItem("property") !== null) && !done)) { /* && !node.attributes.getNamedItem("property").nodeValue.equals(propertyName)))) {*/ |
| var nval = node.attributes.getNamedItem("property")?.nodeValue |
| if(propertyName.equals(nval)) { |
| done = true |
| } else { |
| 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 || type == EType.TIMESTAMP) { |
| 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(String prefix, Document doc, Element parent, String paramName, String paramValue) { |
| var param = doc.createElement(prefix+":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) { |
| 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 = "true" |
| 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 daoValue |
| } |
| |
| def Element createDaoInserter(Document doc, String beanIdName, String elementMap) { |
| var inserter = doc.createElement("dao:inserter") |
| doc.documentElement.appendChild(inserter) |
| var beanId = doc.createAttribute("beanId") |
| beanId.textContent = beanIdName |
| inserter.attributeNode = beanId |
| if(elementMap !== null) { |
| var create = doc.createAttribute("insertOnElement") |
| create.textContent = elementMap |
| inserter.attributeNode = create |
| } |
| return inserter |
| } |
| |
| 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 = <LFeature>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) { |
| 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) { |
| createExportAttribute(dataInterchange, path, f, fieldList, vectorMap) |
| if(f instanceof LEntityAttribute && f.type instanceof LBean) { |
| var beanAttr = (f as LEntityAttribute).type as LBean |
| for(ba : beanAttr.allFeatures) { |
| createExportAttribute(dataInterchange, path, ba, fieldList, vectorMap) |
| } |
| } |
| } |
| } |
| // 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) |
| } |
| if(endPoint instanceof DataInterchangeFileFixed) { |
| createFreemarker(doc, createFixedTemplate(rootEntityName, fieldList, dataInterchange.path), endPoint) |
| } |
| } |
| |
| def createExportAttribute(DataInterchange dataInterchange, DataInterchangeBean path, LFeature f, List<LFeature> fieldList, Map<String, String> vectorMap) { |
| if(dataInterchange.getExportFilter === null && f instanceof LAttribute && !f.toMany || |
| dataInterchange.getExportFilter !== null && |
| f instanceof LAttribute && !f.toMany && |
| dataInterchange.getExportFilter.hiddenproperties !== null && |
| !dataInterchange.getExportFilter.hiddenproperties.empty && |
| !dataInterchange.getExportFilter.hiddenproperties.toList.containsFeature(f)) { |
| if(useFeature(f, path, dataInterchange)) { |
| fieldList.add(f) |
| } |
| } |
| if(f instanceof LReference && !f.toMany && path.lookupKeys.empty) { |
| fieldList.add(f) |
| } |
| // 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) { |
| if(next.refDataSource !== null){ |
| vectorMap.put(next.entity.toName, '''«path.entity.toName».«next.refDataSource.name»''') |
| } |
| else{ |
| vectorMap.put(next.entity.toName, '''«path.entity.toName».«f.name»''') |
| } |
| } |
| } |
| } |
| } |
| |
| 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<LFeature> fieldList, Document doc, DataInterchangeFile endPoint) { |
| var isFirst = true |
| var autoMapping = "" |
| var byAttribute = false |
| var isMarked = false |
| switch(endPoint) { |
| DataInterchangeFileCSV: |
| autoMapping = "/csv-set" |
| DataInterchangeFileXML: { |
| autoMapping = '''«IF dataInterchange.vectorName !== null»«dataInterchange.vectorName»«ELSE»vector«ENDIF»''' |
| byAttribute = endPoint.byAttribute |
| } |
| DataInterchangeFileEDI: {} |
| DataInterchangeFileFixed: |
| autoMapping = "/set" |
| } |
| for(path : dataInterchange.path) { |
| var map = "" |
| if(path.elementMap === null) { |
| map = autoMapping |
| } else { |
| map = path.elementMap |
| } |
| var Element bean = null |
| if(!path.isMarkLatestImport && 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 |
| } else { |
| isMarked = true |
| } |
| switch(endPoint) { |
| DataInterchangeFileCSV: { |
| if(!path.isMarkLatestImport) { |
| autoMapping = autoMapping + "/csv-record" |
| } |
| } |
| DataInterchangeFileXML: { |
| autoMapping = '''«autoMapping»/«IF path.nodeName !== null»«path.nodeName»«ELSE»«path.entity.toName»«ENDIF»''' |
| } |
| DataInterchangeFileEDI: {} |
| DataInterchangeFileFixed: { |
| autoMapping = autoMapping + "/record" |
| } |
| } |
| 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) |
| createDaoQuery(doc, locator, path.queryKeys) |
| createLookupKeys(path, doc, locator, map, byAttribute, endPoint) |
| } |
| 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) |
| createDaoQuery(doc, locator, path.queryVersion) |
| createDaoParam(doc, locator, '''param''', path.entity.primaryKeyAttribute.decoder, map, path.entity.idAttributeName, byAttribute) |
| } |
| } else if(!isMarked && !path.hasBlob) { |
| createDaoInserter(doc, path.entity.toName, map) |
| } |
| // 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) && (!isId(f) || (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) { |
| if((f as LEntityAttribute).type instanceof LBean) { |
| var beanAttr = (f as LEntityAttribute).type as LBean |
| for(ba : beanAttr.allAttributes) { |
| fieldList.add(ba) |
| } |
| } else { |
| fieldList.add(f) |
| } |
| } |
| if(bean !== null) { |
| if((f as LEntityAttribute).type instanceof LBean) { |
| var beanAttr = (f as LEntityAttribute).type as LBean |
| var subBean = createBean(doc, beanAttr.toName, beanAttr.fullyQualifiedName.toString, map, false) |
| for(ba : beanAttr.allAttributes) { |
| createImportAttribute(path, ba, doc, subBean, byAttribute, endPoint, mappingFound) |
| } |
| createWiring(doc, bean, beanAttr.toName, null, f.toSetter.simpleName) |
| } else { |
| createImportAttribute(path, f, doc, bean, byAttribute, endPoint, mappingFound) |
| } |
| } |
| } |
| } |
| } |
| // 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) { |
| if(mapping instanceof DataInterchangePropertyMapping) { |
| 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 |
| var paramCnt = 0 |
| 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) |
| createDaoQuery(doc, locator, (f.type as LEntity).query(lookup, paramCnt)) |
| createDaoParam(doc, locator, '''param«paramCnt»''', lookup.queryProperty.type.name.toFirstUpper, lookup.elementMap, lookup.dataMap, byAttribute) |
| paramCnt ++ |
| if(lookup.condition !== null && lookup.condition.operand instanceof DataInterchangeLookupFilterOperandProperty && !lookup.condition.operator.literal.startsWith("is")) { |
| var prop = (lookup.condition.operand as DataInterchangeLookupFilterOperandProperty).refProperty |
| for(mapping:path.mappings) { |
| if(mapping instanceof DataInterchangePropertyMapping) { |
| if(mapping.property.equals(prop)) { |
| if(mapping.data === null) { |
| createDaoParam(doc, locator, '''param«paramCnt»''', prop.type.name.toFirstUpper, autoMapping, prop.toName, byAttribute) |
| } else { |
| createDaoParam(doc, locator, '''param«paramCnt»''', prop.type.name.toFirstUpper, mapping.data, prop.toName, byAttribute) |
| } |
| paramCnt ++ |
| } |
| } |
| } |
| } |
| if(lookup.condition !== null && lookup.condition.subcondition !== null) { |
| lookup.condition.subcondition.iterateConditionParameter(doc, locator, path.mappings, autoMapping, paramCnt, byAttribute) |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| def createImportAttribute(DataInterchangeBean path, LAttribute f, Document doc, Element parentElement, boolean byAttribute, DataInterchangeFile endPoint, boolean mappingFound) { |
| // scan expressions for this field |
| var expressionFound = path.createAttributeExpression(f, doc, parentElement) |
| // scan formats for this field |
| var formatFound = path.createAttributeFormat(f, doc, parentElement, endPoint) |
| // 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)) { |
| path.createAttributeMapping(f as LAttribute, doc, parentElement, endPoint) |
| } |
| } |
| } |
| createAttributeMapping(path, f, doc, parentElement, byAttribute) |
| // default mapping for xml and csv |
| if (!mappingFound && !path.isMarkLatestImport && (endPoint instanceof DataInterchangeFileXML||endPoint instanceof DataInterchangeFileCSV)) { |
| addMapping(doc, parentElement, f.toName, f.toName, byAttribute) |
| } |
| } |
| |
| def boolean isId(LFeature f) { |
| if(f instanceof LEntityAttribute) { |
| return (f as LEntityAttribute).id || (f as LEntityAttribute).uuid |
| } |
| return false |
| } |
| |
| protected def boolean hasBlob(DataInterchangeBean path) { |
| for(mapping : path.mappings) { |
| if(mapping instanceof DataInterchangeBlobMapping) { |
| return true |
| } |
| } |
| } |
| |
| protected def void createAttributeMapping(DataInterchangeBean path, LAttribute f, Document doc, Element parentElement, boolean byAttribute) { |
| for(mapping : path.mappings) { |
| switch(mapping) { |
| DataInterchangePropertyMapping: { |
| if(f.name.equals(mapping.property.name)) { |
| if(mapping.data === null || mapping.data.empty) { |
| addMapping(doc, parentElement, f.toName, f.toName, byAttribute) |
| } else { |
| addMapping(doc, parentElement, f.toName, mapping.data, byAttribute) |
| } |
| } |
| } |
| DataInterchangeLookupMapping: {} |
| DataInterchangeSkipMapping: {} |
| } |
| } |
| } |
| |
| def createAttributeMapping(DataInterchangeBean path, LAttribute f, Document doc, Element parentElement, DataInterchangeFile endPoint) { |
| var etype = dtType.getBasicType(f) |
| // add enum decoder |
| if(etype == EType.LENUM){ |
| var value = createProperty(doc, parentElement, f.toName, "Enum", etype) |
| createDecodeParam("jb", doc, value, "enumType", f.type.toQualifiedName.toString) |
| |
| var enumsliterals = f.type.eContents; |
| for(literal : enumsliterals){ |
| val enumname = literal.fullyQualifiedName.lastSegment |
| // extra fileds |
| createDecodeParam("jb", doc, value, enumsliterals.indexOf(literal).toString, enumname) |
| // mandatory fields |
| createDecodeParam("jb", doc, value, enumname, enumname) |
| } |
| } |
| else{ |
| // add format decoder |
| var Element value = null |
| value = createProperty(doc, parentElement, f.toName, f.decoder, etype) |
| createDefaultDecoderFormat("jb", doc, value, f, endPoint) |
| } |
| } |
| |
| protected def createDefaultDecoderFormat(String prefix, Document doc, Element parentElement, LAttribute f, DataInterchangeFile endPoint) { |
| var etype = dtType.getBasicType(f) |
| if (etype == EType.DATE || etype == EType.TIMESTAMP) { |
| createDecodeParam(prefix, doc, parentElement, "format", "yyyy-MM-dd'T'HH:mm:ss") |
| } else if((etype == EType.DOUBLE || etype == EType.FLOAT) && endPoint.locale !== null) { |
| createDecodeParam(prefix, doc, parentElement, "format", "#.######") |
| if (endPoint.locale !== null) { |
| createDecodeParam(prefix, doc, parentElement, "locale-language", endPoint.locale.split("_").get(0)) |
| if(endPoint.locale.split("_").size > 1) { |
| createDecodeParam(prefix, doc, parentElement, "locale-country", endPoint.locale.split("_").get(1)) |
| } |
| } |
| } |
| } |
| |
| protected def boolean createAttributeFormat(DataInterchangeBean path, LAttribute f, Document doc, Element parentElement, DataInterchangeFile endPoint) { |
| 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, parentElement, f.toName, f.decoder, dtType.getBasicType(f)) |
| if(format.format !== null) { |
| createDecodeParam("jb", doc, value, "format", format.format) |
| |
| if (endPoint.locale !== null) { |
| createDecodeParam("jb", doc, value, "locale-language", endPoint.locale.split("_").get(0)) |
| if(endPoint.locale.split("_").size > 1) { |
| createDecodeParam("jb", doc, value, "locale-country", endPoint.locale.split("_").get(1)) |
| } |
| } |
| |
| } |
| formatFound = true |
| } |
| } |
| return formatFound |
| } |
| |
| protected def boolean createAttributeExpression(DataInterchangeBean path, LAttribute f, Document doc, Element parentElement) { |
| var expressionFound = false |
| 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, parentElement, 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, parentElement, f.toName, "PUUID."+(expr as DataInterchangePredefinedExpression).beanType.getName) |
| } else { |
| createExpression(doc, parentElement, f.toName, "PTIME."+(expr as DataInterchangePredefinedExpression).bean.getName+(expr as DataInterchangePredefinedExpression).beanType.getName) |
| } |
| expressionFound = true |
| } |
| } |
| } |
| } |
| return expressionFound |
| } |
| |
| protected def void createLookupKeys(DataInterchangeBean path, Document doc, Element locator, String map, boolean byAttribute, DataInterchangeFile endPoint) { |
| var pCnt = 0 |
| for(key:path.lookupKeys) { |
| if(key.property.eContainer.equals(path.entity)) { |
| var daoValue = createDaoParam(doc, locator, '''param«pCnt»''', key.property.decoder, map, path.mappings.mapElement(key.property.name), byAttribute) |
| createDefaultDecoderFormat("dao", doc, daoValue, key.property, endPoint) |
| } else { |
| for(lookup:path.lookup) { |
| if(lookup.queryProperty.equals(key.property)) { |
| var daoValue = createDaoParam(doc, locator, '''param«pCnt»''', key.property.decoder, map, lookup.elementMap.replace(map, "").replace("//", ""), byAttribute) |
| createDefaultDecoderFormat("dao", doc, daoValue, key.property, endPoint) |
| } |
| } |
| } |
| pCnt ++ |
| } |
| } |
| |
| def boolean hasAnnotation(LFeature feature, Class<?> annotationType) { |
| for(anno:(feature).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 instanceof LEntityAttribute) { |
| 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) { |
| if(mapping instanceof DataInterchangePropertyMapping) { |
| 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 instanceof DataInterchangePropertyMapping && (it as DataInterchangePropertyMapping).property.name.equals(attribute.name)].empty |
| } |
| return false; |
| } |
| |
| def String mapElement(EList<DataInterchangeMapping> mappings, String propertyName) { |
| var element = (mappings.findFirst[it instanceof DataInterchangePropertyMapping && (it as DataInterchangePropertyMapping).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) { |
| var LAttribute prevAttr = null |
| 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(useFeature(p, path, dataInterchange)) { |
| if(p instanceof LAttribute && p.type instanceof LBean) { |
| prevAttr = p as LAttribute |
| } else { |
| var format = null as DataInterchangeFormat |
| for (step : formats) { |
| // is there a format modeled for this attribute ? |
| if ((p as LFeature).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, -1, prevAttr?.toName, null) |
| 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, -1, "", segments) |
| bean.appendChild(property) |
| } |
| var pa = doc.createProcessingInstruction(currentKey, "") |
| if(parent === null) { |
| doc.documentElement.appendChild(pa) |
| } else { |
| parent.appendChild(pa) |
| } |
| return bean |
| } |
| |
| def boolean useFeature(LFeature f, DataInterchangeBean path, DataInterchange dataInterchange) { |
| var mappingFound = hasAttributeMapping(path) |
| if (!isInternal(f) && // don't export version etc. |
| !path.isMarkLatestImport && (!mappingFound || path.mappings.isMapped(f))) { |
| if(dataInterchange.mode == EntityManagerMode.PERSIST) { |
| if(isId(f)) { |
| return false |
| } |
| return true |
| } else { |
| return true |
| } |
| } |
| return false |
| } |
| |
| def String decoder(LFeature f) { |
| return getPrimitiveDataTypeName(f as LAttribute) |
| } |
| |
| def String decoder(LEntityAttribute f) { |
| return getPrimitiveDataTypeName(f) |
| } |
| |
| def String getPrimitiveDataTypeName(LAttribute attribute) { |
| var eType = dtType.getBasicType(attribute) |
| var String typeName = null |
| if (eType == EType.DATE || eType == EType.TIMESTAMP) { |
| 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 |
| |
| var DataInterchange interchange = null |
| // processing the template string for filtered information |
| for(f: path){ // for exclusion |
| if(f.eContainer instanceof DataInterchange){ |
| interchange = f.eContainer as DataInterchange |
| } |
| if(interchange !== null && interchange.getExportFilter !== null && interchange.getExportFilter.hiddenproperties !== null && !interchange.getExportFilter.hiddenproperties.empty){ |
| for(hiddenprop : interchange.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(DataInterchangeBean bean, List<LFeature> fieldList, String delimiter, String quote, EList<DataInterchangeBean> paths) { |
| var rootEntityName = (bean.entity as LAnnotationTarget).toName.toString |
| var tmpList = <String>newArrayList() |
| var fldList = <String>newArrayList |
| var LAttribute prevAttr = null |
| for(field:fieldList) { |
| if(field instanceof LAttribute && field.type instanceof LBean) { |
| prevAttr = field as LAttribute |
| } else { |
| tmpList.add(encodeFreemarker(rootEntityName, field, paths, quote, false, -1, prevAttr?.toName)) |
| fldList.add(field.toName) |
| } |
| } |
| for(e : bean.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 pathToProperty = segments.join(".") |
| tmpList.add(encodeFreemarker('''«rootEntityName».«pathToProperty»''', expose.refProperty, paths, quote, false, -1, "")) |
| fldList.add(expose.refProperty.name) |
| } |
| |
| var body = ''' |
| «fldList.join(delimiter)» |
| <#list vector as «rootEntityName»> |
| «tmpList.join(delimiter)» |
| </#list>''' |
| return body |
| } |
| |
| def String createFixedTemplate(String rootEntityName, List<LFeature> fieldList, EList<DataInterchangeBean> paths) { |
| var tmpList = <String>newArrayList() |
| for(path:paths) { |
| for(map:path.mappings) { |
| var column = map as DataInterchangeFixedColumnMapping |
| tmpList.add(encodeFreemarker(rootEntityName, column.property, paths, null, false, column.length, null)) |
| } |
| } |
| var body = ''' |
| <#list vector as «rootEntityName»> |
| «tmpList.join()» |
| </#list>''' |
| return body |
| } |
| |
| def String encodeFreemarker(String entityName, LFeature field, EList<DataInterchangeBean> paths, String quote, boolean encodeHtml, int length, String beanPrefix) { |
| var format = null as DataInterchangeFormat |
| var LEntity entity = null |
| if(field.eContainer instanceof LEntity) { |
| 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, length, beanPrefix, null) |
| } |
| |
| def String encodeFreemarker(String entityName, LFeature field, DataInterchangeFormat format, String quote, boolean encodeHtml, int length, String beanPrefix, List<String> segments) { |
| var EType etype = null |
| var String fldName = null |
| var template = "" |
| if(field instanceof LEntityAttribute) { |
| fldName = '''«entityName».«field.toName»''' |
| etype = dtType.getBasicType(field) |
| } |
| if(field instanceof LBeanAttribute) { |
| fldName = '''«entityName».«beanPrefix».«field.toName»''' |
| etype = dtType.getBasicType(field) |
| } |
| if(field instanceof LEntityAttribute || field instanceof LBeanAttribute) { |
| if (etype == EType.BOOLEAN) { |
| template = '''${(«fldName»?c«fixedLength(length)»)!«fixedLength(length)»}''' |
| return if(segments !== null) encodeFreeMarkerForExpose(entityName, segments, template, null, null) else template |
| } |
| else if (format !== null) { |
| template = '''${(«fldName»?string["«format.format»"]«fixedLength(length)»)!«fixedLength(length)»}''' |
| return if(segments !== null) encodeFreeMarkerForExpose(entityName, segments, template, null, null) else template |
| } |
| else if (etype == EType.DATE || etype == EType.TIMESTAMP) { |
| template = '''${(«fldName»?datetime?iso_local_ms_nz)«fixedLength(length)»!«fixedLength(length)»}''' |
| return if(segments !== null) encodeFreeMarkerForExpose(entityName, segments, template, null, null) else template |
| } |
| else if (etype == EType.STRING) { |
| template = '''«quote»${(«fldName»«IF encodeHtml»?html«ENDIF»«fixedLength(length)»)!«fixedLength(length)»}«quote»''' |
| return if(segments !== null) encodeFreeMarkerForExpose(entityName, segments, template, null, null) else template |
| } |
| else { |
| template = '''${(«fldName»)«fixedLength(length)»!«fixedLength(length)»}''' |
| return if(segments !== null) encodeFreeMarkerForExpose(entityName, segments, template, null, null) else template |
| } |
| } |
| if(field instanceof LEntityReference) { |
| etype = dtType.getBasicType((field as LEntityReference).type.primaryKeyAttribute) |
| if (etype == EType.STRING) { |
| template = '''«quote»${(«entityName».«field.toName».«(field as LEntityReference).type.primaryKeyAttribute.name»«fixedLength(length)»)!«fixedLength(length)»}«quote»''' |
| return if(segments !== null) encodeFreeMarkerForExpose(entityName, segments, template, null, null) else template |
| } else { |
| template = '''${(«entityName».«field.toName».«(field as LEntityReference).type.primaryKeyAttribute.name»«fixedLength(length)»)!«fixedLength(length)»}''' |
| return if(segments !== null) encodeFreeMarkerForExpose(entityName, segments, template, null, null) else template |
| } |
| } |
| } |
| |
| def String encodeFreeMarkerForExpose(String entityName, List<String> segments, String fieldexpression, String prefix, String sufix){ |
| var part = entityName.substring(0, entityName.indexOf(".")) |
| var part1 = "" |
| var part2 = "" |
| |
| if(segments === null || (segments.get(0) !== null && segments.get(0).isEmpty)){ |
| return fieldexpression |
| } |
| else{ |
| for(String segment : segments){ |
| part = '''«part».«segment»''' |
| part1 = part1.concat('''<#if «part»?exists>''') |
| part2 = part2.concat('''</#if>''') |
| } |
| } |
| return part1.concat(fieldexpression).concat(part2) |
| } |
| |
| def fixedLength(int length) |
| '''«IF length > 0»?right_pad(«length»)[0..*«length»]«ENDIF»''' |
| |
| /* 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, int paramCnt) { |
| var pCnt = paramCnt |
| 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«pCnt++»''' |
| whereList.add(qstr) |
| if(lookup.condition !== null) { |
| var lstr = '''x«aliasCnt».«lookup.condition.refProperty.toName» «lookup.condition.operator» «IF lookup.condition.operand instanceof DataInterchangeLookupFilterOperandString»'«(lookup.condition.operand as DataInterchangeLookupFilterOperandString).value»'«ELSE»:param«pCnt++»«ENDIF»''' |
| if(lookup.condition.subcondition !== null) { |
| lstr = lstr + " " + lookup.condition.operator2.literal + " " |
| lstr = lookup.condition.subcondition.iterateCondition(lstr, aliasCnt, pCnt) |
| } |
| whereList.add("("+lstr+")") |
| } |
| 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 iterateCondition(DataInterchangeLookupFilterCondition condition, String input, int aliasCnt, int paramCnt) { |
| var pCnt = paramCnt |
| var lstr = '''«input»x«aliasCnt».«condition.refProperty.toName» «condition.operator» «IF condition.operand instanceof DataInterchangeLookupFilterOperandString»'«(condition.operand as DataInterchangeLookupFilterOperandString).value»'«ELSEIF !condition.operator.literal.startsWith("is")»:param«pCnt++»«ENDIF»''' |
| if(condition.subcondition !== null) { |
| lstr = lstr + " " + condition.operator2.literal + " " |
| lstr = condition.subcondition.iterateCondition(lstr, aliasCnt, pCnt) |
| } |
| return lstr |
| } |
| |
| def void iterateConditionParameter(DataInterchangeLookupFilterCondition condition, Document doc, Element locator, EList<DataInterchangeMapping> mappings, String autoMapping, int paramCnt, boolean byAttribute) { |
| var pCnt = paramCnt |
| if(condition.operand instanceof DataInterchangeLookupFilterOperandProperty && !condition.operator.literal.startsWith("is")) { |
| var prop = (condition.operand as DataInterchangeLookupFilterOperandProperty).refProperty |
| for(mapping:mappings) { |
| if(mapping instanceof DataInterchangePropertyMapping) { |
| if(mapping.property.equals(prop)) { |
| if(mapping.data === null) { |
| createDaoParam(doc, locator, '''param«paramCnt»''', prop.type.name.toFirstUpper, autoMapping, prop.toName, byAttribute) |
| } else { |
| createDaoParam(doc, locator, '''param«paramCnt»''', prop.type.name.toFirstUpper, mapping.data, prop.toName, byAttribute) |
| } |
| pCnt ++ |
| } |
| } |
| } |
| } |
| if(condition.subcondition !== null) { |
| condition.subcondition.iterateConditionParameter(doc, locator, mappings, autoMapping, pCnt, byAttribute) |
| } |
| } |
| |
| def String queryKeys(DataInterchangeBean bean) { |
| var pCnt = 0 |
| var eCnt = -1 |
| var LEntity oldEntity = null |
| var select = '''«bean.entity.toName» x«pCnt»''' |
| var rootAlias = '''x«pCnt»''' |
| var whereList = <String>newArrayList |
| for(key:bean.lookupKeys) { |
| if(key.property.eContainer.equals(bean.entity)) { |
| if(!key.property.eContainer.equals(oldEntity)) { |
| eCnt ++ |
| oldEntity = key.property.eContainer as LEntity |
| } |
| var qstr = '''x«eCnt».«key.property.toName» = :param«pCnt»''' |
| whereList.add(qstr) |
| } else { |
| for(lookup:bean.lookup) { |
| if(lookup.queryProperty.equals(key.property)) { |
| if(!lookup.queryProperty.equals(oldEntity)) { |
| eCnt ++ |
| oldEntity = lookup.queryProperty as LEntity |
| } |
| select = '''«select» left join «lookup.entity.toName» x«pCnt» on(x«pCnt»=«rootAlias».«lookup.targetProperty.toName»)''' |
| var qstr = '''x«eCnt».«key.property.toName» = :param«pCnt»''' |
| whereList.add(qstr) |
| } |
| } |
| } |
| pCnt ++; |
| } |
| 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, LFeature 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 |
| , TransformerConfigurationException |
| , SAXException |
| , IOException |
| , UUID |
| , IOException |
| , File |
| , FileInputStream |
| , Properties |
| , ProductConfiguration |
| , PrintWriter |
| , BlobService |
| , BlobTypingAPI |
| , Component |
| , Panel |
| , Paths |
| , Date |
| , Metamodel |
| , EntityType |
| , ListJoin |
| , Join |
| ) |
| super.createAppendable(context, importManager, config) |
| } |
| } |