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