blob: c84284f50b28d8e96fc739cb1413c657cfc949f2 [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 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.ui.Button
import com.vaadin.ui.CssLayout
import com.vaadin.ui.Label
import com.vaadin.ui.Panel
import com.vaadin.ui.VerticalLayout
import java.io.OutputStream
import java.net.URL
import java.nio.file.Path
import java.util.ArrayList
import java.util.HashMap
import java.util.Locale
import java.util.Map
import java.util.concurrent.ExecutorService
import javax.annotation.PostConstruct
import javax.annotation.PreDestroy
import javax.inject.Inject
import javax.persistence.EntityManager
import javax.xml.transform.Transformer
import javax.xml.transform.TransformerFactory
import org.eclipse.e4.core.contexts.IEclipseContext
import org.eclipse.e4.ui.di.Focus
import org.eclipse.e4.ui.model.application.MApplication
import org.eclipse.osbp.core.api.persistence.IPersistenceService
import org.eclipse.osbp.datainterchange.api.IDataInterchange
import org.eclipse.osbp.dsl.entity.xtext.extensions.ModelExtensions
import org.eclipse.osbp.dsl.semantic.common.types.LReference
import org.eclipse.osbp.dsl.semantic.entity.LEntity
import org.eclipse.osbp.osgi.hybrid.api.AbstractHybridVaaclipseView
import org.eclipse.osbp.runtime.common.event.EventDispatcherEvent
import org.eclipse.osbp.runtime.common.event.IEventDispatcher
import org.eclipse.osbp.ui.api.customfields.IBlobService
import org.eclipse.osbp.ui.api.e4.IE4Focusable
import org.eclipse.osbp.ui.api.metadata.IDSLMetadataService
import org.eclipse.osbp.ui.api.user.IUser
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.DataInterchangeExportFilter
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.DataInterchangeFilterCondition
import org.eclipse.osbp.xtext.datainterchange.DataInterchangeGroup
import org.eclipse.osbp.xtext.datainterchange.DataInterchangePackage
import org.eclipse.osbp.xtext.datainterchange.EntityManagerMode
import org.eclipse.osbp.xtext.datainterchange.common.WorkerThreadRunnable
import org.eclipse.osbp.xtext.datainterchange.common.WorkerThreadRunnable.Direction
import org.eclipse.osbp.xtext.entitymock.common.IEntityImportInitializationListener
import org.eclipse.osbp.xtext.i18n.DSLOutputConfigurationProvider
import org.eclipse.xtext.common.types.JvmDeclaredType
import org.eclipse.xtext.common.types.JvmField
import org.eclipse.xtext.common.types.JvmGenericType
import org.eclipse.xtext.common.types.JvmVisibility
import org.eclipse.xtext.naming.IQualifiedNameProvider
import org.eclipse.xtext.xbase.jvmmodel.AbstractModelInferrer
import org.eclipse.xtext.xbase.jvmmodel.IJvmDeclaredTypeAcceptor
import org.eclipse.xtext.xbase.jvmmodel.JvmTypesBuilder
import org.osgi.framework.BundleEvent
import org.osgi.framework.BundleListener
import org.slf4j.Logger
/**
* <p>
* Data Interchange Repository Domain Specific Language
* This inferrer infers models of extension .data and generates code to be used by any data interchanging process
* to facilitate the communication with external data sources and drains.
* </p>
*
* @author Joerg Riegel
*/
class DataDSLJvmModelInferrer extends AbstractModelInferrer {
@Inject extension JvmTypesBuilder
@Inject extension IQualifiedNameProvider
@Inject extension DataDSLModelGenerator dg
@Inject extension ModelExtensions
/* ramp up NTHREADS and threads are finished start more but up to this limit */
var NTHREADS = 10;
/**
* infer model on package base. Will be called for every defined package.
*
* @param group
* An instance of {@link DataInterchangeGroup}
* @param acceptor
* the xtext acceptor interface
* @param isPreIndexingPhase
* true if in preindexing phase
*/
def dispatch void infer(DataInterchangeGroup group, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
(group.eContainer as DataInterchangePackage).generatePckgName(acceptor)
// create a view
var cls = group.toClass(group.name + "TriggerView");
cls.simpleName = cls.simpleName.toFirstUpper
acceptor.accept(cls,
[
superTypes += _typeReferenceBuilder.typeRef(AbstractHybridVaaclipseView)
superTypes += _typeReferenceBuilder.typeRef(BundleListener)
superTypes += _typeReferenceBuilder.typeRef(IUser.UserLocaleListener)
superTypes += _typeReferenceBuilder.typeRef(IEventDispatcher.Receiver)
superTypes += _typeReferenceBuilder.typeRef(IE4Focusable)
packageName = DataDSLModelGenerator.pckgName
it.fileHeader = group.documentation
it.toFields(group)
it.toConstructor(group)
it.toOperations(group)
])
// create classes
group.datInts.forEach[dataInterchange|
var clsName2 = DataDSLModelGenerator.pckgName+"."+dataInterchange.name
acceptor.accept(dataInterchange.toClass(clsName2),
[
superTypes += _typeReferenceBuilder.typeRef(WorkerThreadRunnable)
annotations += _annotationTypesBuilder.annotationRef(SuppressWarnings, "serial")
packageName = DataDSLModelGenerator.pckgName
it.fileHeader = group.documentation
it.toConstructor(dataInterchange)
it.toFields(dataInterchange)
it.toOperations(dataInterchange)
])
]
}
/**
* generate the fields in the inferred class.
*
* @param type
* the xtext generic types list
* @param pkg
* the current package inferred {@link DataInterchangePackage}
*/
def void toFields(JvmGenericType type, DataInterchangeGroup group) {
var JvmField field = null
field = group.toField("sidebar", _typeReferenceBuilder.typeRef(VerticalLayout))
type.members += field
field = group.toField("log", _typeReferenceBuilder.typeRef(Logger)) [setInitializer([ append('''LoggerFactory.getLogger(«group.fullyQualifiedName.lastSegment.toFirstUpper»TriggerView.class)''') ])]
field.final = true
field.static = true
type.members += field
field = group.toField("menu", _typeReferenceBuilder.typeRef(CssLayout))
type.members += field
field = group.toField("menuPanel", _typeReferenceBuilder.typeRef(Panel))
type.members += field
field = group.toField("branding", _typeReferenceBuilder.typeRef(CssLayout))
type.members += field
field = group.toField("persistenceService", _typeReferenceBuilder.typeRef(IPersistenceService)) [
annotations += _annotationTypesBuilder.annotationRef(Inject)
]
type.members += field
field = group.toField("progressBars", _typeReferenceBuilder.typeRef(Map, _typeReferenceBuilder.typeRef(String), _typeReferenceBuilder.typeRef(WorkerThreadRunnable)))
type.members += field
field = group.toField("executorService", _typeReferenceBuilder.typeRef(ExecutorService))
field.static = true
type.members += field
field = group.toField("dslMetadataService", _typeReferenceBuilder.typeRef(IDSLMetadataService)) [annotations += _annotationTypesBuilder.annotationRef(Inject)]
type.members += field
field = group.toField("dataInterchange", _typeReferenceBuilder.typeRef(IDataInterchange)) [annotations += _annotationTypesBuilder.annotationRef(Inject)]
type.members += field
field = group.toField("eventDispatcher", _typeReferenceBuilder.typeRef(IEventDispatcher))[annotations += _annotationTypesBuilder.annotationRef(Inject)]
type.members += field
field = group.toField("blobService", _typeReferenceBuilder.typeRef(IBlobService))[annotations += _annotationTypesBuilder.annotationRef(Inject)]
type.members += field
field = group.toField("user", _typeReferenceBuilder.typeRef(IUser))[annotations += _annotationTypesBuilder.annotationRef(Inject)]
type.members += field
field = group.toField("logo", _typeReferenceBuilder.typeRef(Label))
type.members += field
field = group.toField("buttons",
_typeReferenceBuilder.typeRef(HashMap, _typeReferenceBuilder.typeRef(Button), _typeReferenceBuilder.typeRef(ArrayList, _typeReferenceBuilder.typeRef(String))))
type.members += field
field = group.toField("panels",
_typeReferenceBuilder.typeRef(HashMap, _typeReferenceBuilder.typeRef(Panel), _typeReferenceBuilder.typeRef(ArrayList, _typeReferenceBuilder.typeRef(String))))
type.members += field
}
/**
* <p>build the constructors to be used by an e4 application.</p>
*
*/
def void toConstructor(JvmDeclaredType type, DataInterchangeGroup group) {
type.members += group.toConstructor([
annotations += _annotationTypesBuilder.annotationRef(Inject)
parameters += group.toParameter("parent", _typeReferenceBuilder.typeRef(VerticalLayout))
parameters += group.toParameter("context", _typeReferenceBuilder.typeRef(IEclipseContext))
parameters += group.toParameter("app", _typeReferenceBuilder.typeRef(MApplication))
body = [ append('''super(parent,context,app);''')]
])
}
/**
* generate the fields in the inferred class.
*
* @param type
* the xtext generic types list
* @param pkg
* the current package inferred {@link DataInterchangePackage}
*/
def void toOperations(JvmGenericType type, DataInterchangeGroup group) {
// create view
type.members += group.toMethod("createView", _typeReferenceBuilder.typeRef(Void::TYPE), [
parameters += group.toParameter("parent", _typeReferenceBuilder.typeRef(VerticalLayout))
body = [ append('''«group.createView»''')]
])
// create components
type.members += group.toMethod("createComponents", _typeReferenceBuilder.typeRef(Void::TYPE), [
body = [ append('''''')]
])
// is duplicate
type.members += group.toMethod("isDuplicate", _typeReferenceBuilder.typeRef(boolean), [
parameters += group.toParameter("name", _typeReferenceBuilder.typeRef(String))
body = [ append('''«isDuplicate»''')]
])
// find layout
type.members += group.toMethod("findButtonLayout", _typeReferenceBuilder.typeRef(VerticalLayout), [
parameters += group.toParameter("button", _typeReferenceBuilder.typeRef(Button))
body = [ append('''«findButtonLayout»''')]
])
// remove progressbar
type.members += group.toMethod("removeProgressBar", _typeReferenceBuilder.typeRef(Void::TYPE), [
parameters += group.toParameter("workerName", _typeReferenceBuilder.typeRef(String))
body = [ append('''«removeProgressBar»''')]
])
// on bundle stopping - shutdown executorService
type.members += group.toMethod("bundleChanged", _typeReferenceBuilder.typeRef(Void::TYPE), [
annotations += _annotationTypesBuilder.annotationRef(Override)
parameters += group.toParameter("event", _typeReferenceBuilder.typeRef(BundleEvent))
body = [ append('''«bundleChanged»''')]
])
// activate
type.members += group.toMethod("activate", _typeReferenceBuilder.typeRef(Void::TYPE),
[
annotations += _annotationTypesBuilder.annotationRef(PostConstruct)
body = [append(
'''
user.addUserLocaleListener(this);
eventDispatcher.addEventReceiver(this);''')]
])
// deactivate
type.members += group.toMethod("deactivate", _typeReferenceBuilder.typeRef(Void::TYPE),
[
annotations += _annotationTypesBuilder.annotationRef(PreDestroy)
body = [append(
'''
user.removeUserLocaleListener(this);
eventDispatcher.removeEventReceiver(this);''')]
])
// focus
type.members += group.toMethod("setFocus", _typeReferenceBuilder.typeRef(Void::TYPE), [
annotations += _annotationTypesBuilder.annotationRef(Focus)
body = [append(
'''
Component parent = getParent();
while(!(parent instanceof Panel) && parent != null) {
parent = parent.getParent();
}
if(parent != null) {
((Panel)parent).focus();
}''')]
])
// locale notification
type.members += group.toMethod("localeChanged", _typeReferenceBuilder.typeRef(Void::TYPE),
[
visibility = JvmVisibility.PUBLIC
annotations += _annotationTypesBuilder.annotationRef(Override)
parameters += group.toParameter("locale", _typeReferenceBuilder.typeRef(Locale))
body = [append('''«group.localeChanged»''')]
])
// event notification
type.members += group.toMethod("receiveEvent", _typeReferenceBuilder.typeRef(Void::TYPE),
[
visibility = JvmVisibility.PUBLIC
annotations += _annotationTypesBuilder.annotationRef(Override)
parameters += group.toParameter("event", _typeReferenceBuilder.typeRef(EventDispatcherEvent))
body = [append('''«receiveEvent»''')]
])
}
/**
* let the app wait for finishing the workers before allowing to stop bundle.
*
* @return code fragment
*/
def String bundleChanged() {
var body = ""
body = '''
«body»
if (event.getType() == BundleEvent.STOPPING) {
log.debug("bundle is stopping");
// This will make the executorService accept no new threads
// and finish all existing threads in the queue
if (executorService != null) {
executorService.shutdown();
// Wait until all threads are finished
try {
executorService.awaitTermination(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
log.debug("all executors finished");
}
'''
return body
}
/**
* find the right button layout for a given button.
*
* @return code fragment
*/
def String findButtonLayout() {
var body = ""
body = '''
«body»
for (Panel panel : panels.keySet()) {
HorizontalLayout buttonCollector = (HorizontalLayout) panel.getContent();
int count = buttonCollector.getComponentCount();
for (int i = 0; i < count; i++) {
VerticalLayout buttonLayout = (VerticalLayout) buttonCollector.getComponent(i);
Button b = (Button) buttonLayout.getComponent(0);
if (b == button) {
return buttonLayout;
}
}
}
return null;
'''
return body
}
/**
* find out if a given thread-id is already running.
*
* @return code fragment
*/
def String isDuplicate() {
var body = ""
body = '''
«body»
boolean found = false;
for(String threadName : progressBars.keySet()) {
if (name.equals(threadName)) {
found = true;
break;
}
}
return found;
'''
return body
}
def String descriptionI18nKey(DataInterchange dataInterchange) {
if ((dataInterchange.descriptionValue === null) || dataInterchange.descriptionValue.isEmpty) {
dataInterchange.name
}
else {
dataInterchange.descriptionValue
}
}
/**
* build an e4 compatible view and create necessary components.
*
* @param pkg
* the current package inferred {@link DataInterchangePackage}
* @return code fragment
*/
def String createView(DataInterchangeGroup group) {
var body = '''
getContext().set(IE4Focusable.class, this);
buttons = new HashMap<>();
panels = new HashMap<>();
Bundle bundle = FrameworkUtil.getBundle(getClass());
if (bundle != null) {
BundleContext ctx = bundle.getBundleContext();
if (ctx != null) {
ctx.addBundleListener(this);
}
}
FrameworkUtil.getBundle(getClass()).getBundleContext().addBundleListener(this);
executorService = Executors.newFixedThreadPool(«NTHREADS»);
progressBars = new HashMap<String,WorkerThreadRunnable>();
sidebar=new VerticalLayout();
menu=new CssLayout();
branding=new CssLayout();
menuPanel = new Panel();
menuPanel.setSizeFull();
parent.setPrimaryStyleName("osbp");
parent.setId("parent");
parent.setSizeFull();
sidebar.setSpacing(true);
sidebar.setId("sidebar");
parent.addComponent(sidebar);
parent.setExpandRatio(sidebar, 1.0f);
// create sidebar
sidebar.addStyleName("osbpsidebar");
sidebar.setSizeFull();
sidebar.addComponent(branding);
// branding title
branding.addStyleName("branding");
logo = new Label();
logo.setContentMode(ContentMode.HTML);
logo.setSizeUndefined();
branding.addComponent(logo);
// add menu
menuPanel.setContent(menu);
sidebar.addComponent(menuPanel);
sidebar.setExpandRatio(menuPanel, 1.0f);
'''
body = '''
«body»
// add menu items
Button b;
VerticalLayout buttonLayout;
Panel buttonPanel;
HorizontalLayout buttonCollector;
'''
for (dataInterchange : group.datInts) {
body = '''
«body»
buttonPanel = new Panel();
buttonPanel.addStyleName("os-group-panel os-caption-large");
buttonPanel.setCaption("«dataInterchange.name»");
buttonCollector = new HorizontalLayout();
buttonCollector.setMargin(true);
buttonPanel.setContent(buttonCollector);
panels.put(buttonPanel, new ArrayList<String>(Arrays.asList(new String[] {"«dataInterchange.name»","«dataInterchange.descriptionI18nKey»"})));
b = new NativeButton();
b.setHtmlContentAllowed(true);
buttons.put(b, new ArrayList<String>(Arrays.asList(new String[] {"«DataDSLModelGenerator.CAPTION__REPFIX_I18NKEY_IMPORT»", "«dataInterchange.name»","«dataInterchange.descriptionI18nKey»"})));
b.addStyleName("icon-download");
b.addClickListener(new ClickListener() {
@Override
public void buttonClick(ClickEvent event) {
log.debug("pressed «dataInterchange.name» import");
«dataInterchange.getBasicRunConfiguration(false, dataInterchange.getFileURL, WorkerThreadRunnable.Direction.IMPORT.name)»
«dataInterchange.defaultVariableName».setName(UUID.randomUUID().toString());
«dataInterchange.defaultVariableName».setEventDispatcher(eventDispatcher);
«dataInterchange.defaultVariableName».setUi(UI.getCurrent());
«dataInterchange.defaultVariableName».setDirection(WorkerThreadRunnable.Direction.IMPORT);
findButtonLayout(event.getButton()).addComponent(«dataInterchange.defaultVariableName».getProgressBarArea());
progressBars.put(«dataInterchange.defaultVariableName».getName(), «dataInterchange.defaultVariableName»);
executorService.execute(«dataInterchange.defaultVariableName»);
log.debug("«dataInterchange.name» import added to executor queue");
}
});
buttonLayout = new VerticalLayout();
buttonLayout.addComponent(b);
buttonCollector.addComponent(buttonLayout);
menu.addComponent(buttonPanel);
'''
body = '''
«body»
b = new NativeButton();
b.setHtmlContentAllowed(true);
buttons.put(b, new ArrayList<String>(Arrays.asList(new String[] {"«DataDSLModelGenerator.CAPTION__REPFIX_I18NKEY_EXPORT»", "«dataInterchange.name»","«dataInterchange.descriptionI18nKey»"})));
b.addStyleName("icon-upload");
b.addClickListener(new ClickListener() {
@Override
public void buttonClick(ClickEvent event) {
log.debug("pressed «dataInterchange.name» export");
«dataInterchange.getBasicRunConfiguration(false, dataInterchange.getFileURL, WorkerThreadRunnable.Direction.EXPORT.name)»
«dataInterchange.defaultVariableName».setName(UUID.randomUUID().toString());
«dataInterchange.defaultVariableName».setEventDispatcher(eventDispatcher);
«dataInterchange.defaultVariableName».setUi(UI.getCurrent());
«dataInterchange.defaultVariableName».setDirection(WorkerThreadRunnable.Direction.EXPORT);
findButtonLayout(event.getButton()).addComponent(«dataInterchange.defaultVariableName».getProgressBarArea());
progressBars.put(«dataInterchange.defaultVariableName».getName(), «dataInterchange.defaultVariableName»);
executorService.execute(«dataInterchange.defaultVariableName»);
log.debug("«dataInterchange.name» export added to executor queue");
}
});
buttonLayout = new VerticalLayout();
buttonLayout.addComponent(b);
buttonCollector.addComponent(buttonLayout);
menu.addComponent(buttonPanel);
'''
}
body = '''
«body»
menu.addStyleName("menu");
menu.setSizeUndefined();
'''
return body
}
def String getDefaultVariableName(DataInterchange dataInterchange) {
return dataInterchange.name.toFirstLower
}
def String getBasicRunConfiguration(DataInterchange dataInterchange, boolean fqClass, String fileURL, String direction) {
var className = ""
if (fqClass) {
className = DataDSLModelGenerator.pckgName+"."+dataInterchange.name
}
else {
className = dataInterchange.name
}
return
'''
«className» «dataInterchange.getDefaultVariableName» = new «className»();
String url = ProductConfiguration.getDatainterchangeConfiguration();
if(url.isEmpty()) {
url = System.getProperty("user.home")+"/.osbee/"+"«(dataInterchange.eContainer as DataInterchangeGroup).name»Config.xml";
}
if(!url.endsWith(".xml") ) {
if(!(url.endsWith("/") || url.endsWith("\\")) ) {
url = url+File.separator;
}
url = url+"«(dataInterchange.eContainer as DataInterchangeGroup).name»Config.xml";
}
File file = new File(url);
if(file.exists()) {
FileInputStream fileInput;
try {
fileInput = new FileInputStream(file);
Properties properties = new Properties();
properties.loadFromXML(fileInput);
fileInput.close();
if(properties.getProperty("«dataInterchange.name»-«direction.toLowerCase()»") == null) {
«dataInterchange.getDefaultVariableName».setFileURL("«fileURL»");
} else {
«dataInterchange.getDefaultVariableName».setFileURL(properties.getProperty("«dataInterchange.name»-«direction.toLowerCase()»"));
}
} catch (IOException e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
log.error("{}", sw.toString());
return;
}
} else {
«dataInterchange.getDefaultVariableName».setFileURL("«fileURL»");
}
«dataInterchange.getDefaultVariableName».setPersistenceService(persistenceService);
«dataInterchange.getDefaultVariableName».setDataInterchange(dataInterchange);
«dataInterchange.getDefaultVariableName».setEventDispatcher(eventDispatcher);
«dataInterchange.getDefaultVariableName».setBlobService(blobService);
«if(direction.equals(Direction.IMPORT.name)){
'''«dataInterchange.getDefaultVariableName».setDeleteFileAfterImport(«dataInterchange.isDeleteFileAfterImport»);'''
'''
}
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
}
return ""
}
/**
* <p>build the constructor for each class.</p>
*
* @param pkg
* the current datainterchange inferred {@link DataInterchange}
*/
def void toConstructor(JvmDeclaredType type, DataInterchange dataInterchange) {
type.members += dataInterchange.toConstructor([
body = [append('''
setName("«dataInterchange.name»");
''')]
])
}
/**
* <p>build the class variables.</p>
*
*/
def void toFields(JvmDeclaredType type, DataInterchange dataInterchange) {
var JvmField field = null
field = dataInterchange.toField("log", _typeReferenceBuilder.typeRef(Logger)) [setInitializer([ append('''LoggerFactory.getLogger("dataInterchange")''') ])]
field.final = true
field.static = true
type.members += field
field = dataInterchange.toField("dataInterchange", _typeReferenceBuilder.typeRef(IDataInterchange))
type.members += field
field = dataInterchange.toField("em", _typeReferenceBuilder.typeRef(EntityManager))
type.members += field
field = dataInterchange.toField("fileURL", _typeReferenceBuilder.typeRef(URL))
type.members += field
field = dataInterchange.toField("file", _typeReferenceBuilder.typeRef(OutputStream))
type.members += field
field = dataInterchange.toField("out", _typeReferenceBuilder.typeRef(OutputStream))
type.members += field
field = dataInterchange.toField("exportPath", _typeReferenceBuilder.typeRef(Path))
type.members += field
field = dataInterchange.toField("transformerFactory", _typeReferenceBuilder.typeRef(TransformerFactory)) [setInitializer([ append('''TransformerFactory.newInstance()''') ])]
type.members += field
field = dataInterchange.toField("transformer", _typeReferenceBuilder.typeRef(Transformer))
type.members += field
}
/**
* <p>build the methods.</p>
*
*/
def void toOperations(JvmDeclaredType type, DataInterchange dataInterchange) {
type.members += dataInterchange.toGetter("dataInterchange", _typeReferenceBuilder.typeRef(IDataInterchange))
type.members += dataInterchange.toSetter("dataInterchange", _typeReferenceBuilder.typeRef(IDataInterchange))
type.members += dataInterchange.toMethod("run", _typeReferenceBuilder.typeRef(Void::TYPE), [
annotations += _annotationTypesBuilder.annotationRef(Override)
body = [ append('''run(null);''')]
])
type.members += dataInterchange.toMethod("run", _typeReferenceBuilder.typeRef(Void::TYPE), [
parameters += dataInterchange.toParameter("importListener", _typeReferenceBuilder.typeRef(IEntityImportInitializationListener))
body = [ append('''«dataInterchange.performInterchange»''')]
])
type.members += dataInterchange.toMethod("init", _typeReferenceBuilder.typeRef(boolean), [
visibility = JvmVisibility.PROTECTED
parameters += dataInterchange.toParameter("direction", _typeReferenceBuilder.typeRef(WorkerThreadRunnable.Direction))
body = [ append('''«dataInterchange.init»''')]
])
type.members += dataInterchange.toMethod("setFileURL", _typeReferenceBuilder.typeRef(Void::TYPE), [
parameters += dataInterchange.toParameter("filePath", _typeReferenceBuilder.typeRef(String))
body = [ append('''«dataInterchange.fileUrl»''')]
])
type.members += dataInterchange.toMethod("getFileURL", _typeReferenceBuilder.typeRef(URL), [
body = [ append('''«dataInterchange.getfileUrl»''')]
])
}
/**
* Give the fileURL back
*/
def getfileUrl(DataInterchange interchange){
'''return this.fileURL;'''
}
/**
* <p>create URL from filepath or other string.</p>
*
* @param pkg
* the current datainterchange inferred {@link DataInterchange}
* @return code fragment
*/
def fileUrl(DataInterchange dataInterchange)
'''
fileURL = null;
String path = filePath;
if (filePath.startsWith("file://") && org.eclipse.osbp.utils.common.SystemInformation.isWindowsOS()) {
path = filePath.substring("file://".length());
}
try {
fileURL = new URL(path);
} catch (MalformedURLException e1) {
if(e1.getMessage().startsWith("unknown protocol") || e1.getMessage().startsWith("no protocol")) {
try {
fileURL = Paths.get(path).toUri().toURL();
} catch (MalformedURLException e2) {
StringWriter sw = new StringWriter();
e2.printStackTrace(new PrintWriter(sw));
log.error("{}", sw.toString());
}
}
}
'''
/**
* init factory to create the core import process.
* setup listeners for UI communication.
* setup persistence layer.
*
* @param pkg
* the current datainterchange inferred {@link DataInterchange}
* @return code fragment
*/
def String init(DataInterchange dataInterchange) {
var firstEntity = (dataInterchange.path.iterator.next as DataInterchangeBean)
var body =
'''
try {
transformerFactory.setAttribute("indent-number", 4);
transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.STANDALONE, "yes");
transformer.setOutputProperty(OutputKeys.MEDIA_TYPE, "text/xml");
// init
setProgressBarEnabled(true);
setProgressIndeterminated(true);
if (log.isDebugEnabled()) log.debug("initializing datainterchange factory");
// get entity manager
if (log.isDebugEnabled()) log.debug("opening entity manager to persist results");
getPersistenceService().registerPersistenceUnit("«firstEntity.entity.persistenceUnit»", «firstEntity.entity.fullyQualifiedName».class);
em = getPersistenceService().getEntityManagerFactory("«firstEntity.entity.persistenceUnit»").createEntityManager();
if(dataInterchange != null) {
dataInterchange.open(FrameworkUtil.getBundle(getClass()),"«DSLOutputConfigurationProvider.SMOOKS_OUTPUT_DIRECTORY»/«dataInterchange.name»-"+direction.toString().toLowerCase()+".xml");
dataInterchange.setEventListener(this);
dataInterchange.setEntityManager(em);
}
«IF dataInterchange.createReport»
if (log.isDebugEnabled()) log.debug("reporting is on - impacting performance");
if(dataInterchange != null) {
String location = FrameworkUtil.getBundle(this.getClass()).getLocation()+"«DSLOutputConfigurationProvider.SMOOKS_OUTPUT_DIRECTORY»/«dataInterchange.name»-"+direction.toString().toLowerCase()+"-report.html";
location = location.replace("reference:file:/", "");
dataInterchange.enableReport(location);
}
«ENDIF»
} catch (TransformerConfigurationException | SAXException | IOException e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
log.error("{}", sw.toString());
return false;
}
if(direction == Direction.EXPORT) {
int openTry = 0;
file = null;
URI uri = null;
try {
uri = fileURL.toURI();
} catch (URISyntaxException e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
log.error("{}", sw.toString());
return false;
}
do {
exportPath = null;
exportPath = Paths.get(uri);
try {
// find a unique name - similar to given
file = Files.newOutputStream(exportPath, StandardOpenOption.CREATE_NEW);
} catch (FileAlreadyExistsException ae) {
openTry ++;
try {
uri = fileURL.toURI();
int pos = uri.getPath().lastIndexOf('.');
if(pos == -1) {
uri = new URI(uri.getScheme()+":"+uri.getPath()+openTry);
} else {
uri = new URI(uri.getScheme()+":"+uri.getPath().substring(0,pos)+openTry+"."+uri.getPath().substring(pos+1));
}
} catch (URISyntaxException e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
log.error("{}", sw.toString());
return false;
}
} catch (IOException e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
log.error("{}", sw.toString());
return false;
}
}while(file == null);
out = new BufferedOutputStream(file);
}
return true;
'''
return body
}
/**
* use factory to create the core import process.
* setup listeners for UI communication.
* setup persistence layer.
*
* @param pkg
* the current datainterchange inferred {@link DataInterchange}
* @return code fragment
*/
def String performInterchange(DataInterchange dataInterchange) {
var firstEntityBean = (dataInterchange.path.iterator.next as DataInterchangeBean)
firstEntityBean.hasBlobMapping = firstEntityBean.mappings.filter(DataInterchangeBlobMapping).size > 0
var body = '''
if(!init(getDirection())) {
return;
}
if(dataInterchange == null) {
log.error("dataInterchange is not present - download from www.osbee.org");
return;
}
try {
log.info(getDirection().name()+" - Start of «dataInterchange.name».");
if(getDirection()==WorkerThreadRunnable.Direction.IMPORT) {
'''
body = '''
«body»
if (importListener != null) {
importListener.notifyInitializationStep("datainterchange «dataInterchange.name.toFirstUpper» load.", 0.4, 0.45, 0, 0);
}
'''
for (path:dataInterchange.path) {
for (lookup:path.lookup) {
if (lookup.cached) {
body = '''
«body»
em.setProperty(PersistenceUnitProperties.CACHE_SIZE_+"«lookup.entity.fullyQualifiedName»", "«lookup.cacheSize»");
'''
}
}
}
// import beans as list if no mark latest, other wise as a single bean
body = '''
«body»
Object result = null;
if (log.isDebugEnabled()) log.debug("filtering starts");
setProgressIndeterminated(false);
InputStream contents = dataInterchange.openStream(fileURL);
setLength(contents.available());
setAvgElementSize(«IF dataInterchange.elementSize==0»10«ELSE»«dataInterchange.elementSize»«ENDIF»);
result = dataInterchange.importSource(contents, "«firstEntityBean.entity.name»«IF !firstEntityBean.isMarkLatestImport»List«ENDIF»"«IF dataInterchange.fileEndpoint.encoding !== null», "«dataInterchange.fileEndpoint.encoding»"«ENDIF»);
if (log.isDebugEnabled()) log.debug("filtering finished");
em.clear(); // detach eventually attached objects
'''
if (!firstEntityBean.isMarkLatestImport) {
body = '''
«body»
if(result != null) {
List<«firstEntityBean.entity.fullyQualifiedName»> «firstEntityBean.entity.name.toFirstLower»List = Arrays.asList((«firstEntityBean.entity.fullyQualifiedName»[]) result);
em.getTransaction().begin();
if (log.isDebugEnabled()) log.debug("persisting results");
int total = «firstEntityBean.entity.name.toFirstLower»List.size();
int count = 0;
long lastStep = System.currentTimeMillis();
if (importListener != null) {
importListener.notifyInitializationStep("datainterchange «dataInterchange.name.toFirstUpper»", 0.4, 0.5, count, total);
}
for(«firstEntityBean.entity.fullyQualifiedName» «firstEntityBean.entity.name.toFirstLower»:«firstEntityBean.entity.name.toFirstLower»List) {
'''
if(firstEntityBean.hasBlobMapping && dataInterchange.mode!=EntityManagerMode.REMOVE){
for(mapping:firstEntityBean.mappings){
if(mapping instanceof DataInterchangeBlobMapping){
var m = (mapping as DataInterchangeBlobMapping)
var blobFileName = '''«firstEntityBean.entity.name.toFirstLower».get«m.property.name.toFirstUpper»()«IF m.blobFileExtension !== null» + ".«m.blobFileExtension»"«ENDIF»'''
body = '''
«body»
try (InputStream inputStream = new BufferedInputStream(
«IF m.blobPath === null»
this.getClass().getClassLoader().getResourceAsStream("/«firstEntityBean.entity.name»/" + «blobFileName»)
«ELSE»
new FileInputStream("«m.blobPath»/" + «blobFileName»)«ENDIF»)) {
String «firstEntityBean.entity.name.toFirstLower»_«m.property.name»Id = getBlobService().createBlobMapping(
inputStream,
«firstEntityBean.entity.name.toFirstLower».get«m.property.name.toFirstUpper»(),
"«m.mimeType»"
);
«firstEntityBean.entity.name.toFirstLower».set«m.property.name.toFirstUpper»(«firstEntityBean.entity.name.toFirstLower»_«m.property.name»Id);
} catch (IOException e) {
log.error(e.getLocalizedMessage());
}
'''
}
}
}
body =
'''
«body»
try {
«IF dataInterchange.mode==EntityManagerMode.PERSIST»em.persist(«firstEntityBean.entity.name.toFirstLower»);
«ELSEIF dataInterchange.mode==EntityManagerMode.MERGE»em.merge(«firstEntityBean.entity.name.toFirstLower»);
«ELSEIF dataInterchange.mode==EntityManagerMode.REMOVE»«firstEntityBean.entity.fullyQualifiedName» toBeRemoved = em.merge(«firstEntityBean.entity.name.toFirstLower»);
em.remove(toBeRemoved);«ENDIF»
}
catch (ConstraintViolationException cve) {
log.error("«firstEntityBean.entity.name.toFirstLower» #"+(count+1)+"/"+total+": "+cve.getLocalizedMessage());
for (ConstraintViolation<?> violation : cve.getConstraintViolations()) {
Object value = violation.getInvalidValue();
if (value == null) {
value = "<null>";
}
log.error("- property:"
+violation.getLeafBean().toString()+"."+violation.getPropertyPath().toString()
+" value:'"+value.toString()
+" violation:"+violation.getMessage());
}
}
count++;
long thisStep = System.currentTimeMillis();
if ((importListener != null) && ((count % importListener.getInitializationSubStepNotifySize() == 0) || (thisStep-lastStep > 2500))) {
lastStep = System.currentTimeMillis();
importListener.notifyInitializationStep("datainterchange «dataInterchange.name.toFirstUpper»", 0.4, 0.5, count, total);
}
}
if (importListener != null) {
importListener.notifyInitializationStep("datainterchange «dataInterchange.name.toFirstUpper»", 0.4, 0.5, count, total);
}
if (log.isDebugEnabled()) log.debug("committing results");
em.getTransaction().commit();
'''
} else {
body = '''
«body»
if(result != null) {
«firstEntityBean.entity.fullyQualifiedName» «firstEntityBean.entity.name.toFirstLower» = («firstEntityBean.entity.fullyQualifiedName») result;
«firstEntityBean.entity.name.toFirstLower».set«firstEntityBean.latestProperty.name.toFirstUpper»(true);
'''
if(firstEntityBean.hasBlobMapping && dataInterchange.mode!=EntityManagerMode.REMOVE){
for(mapping:firstEntityBean.mappings){
if(mapping instanceof DataInterchangeBlobMapping){
var m = (mapping as DataInterchangeBlobMapping)
var blobFileName = '''«firstEntityBean.entity.name.toFirstLower».get«m.property.name.toFirstUpper»()«IF m.blobFileExtension !== null» + "." + "«m.blobFileExtension»"«ENDIF»'''
body = '''
«body»
try (InputStream inputStream = new BufferedInputStream(
«IF m.blobPath === null»
this.getClass().getClassLoader().getResourceAsStream("/«firstEntityBean.entity.name»/" + «blobFileName»)
«ELSE»
new FileInputStream("«m.blobPath»/" + «blobFileName»)«ENDIF»)) {
String «m.property.name.toFirstLower»Id = blobUpload.createBlobMapping(
inputStream,
«firstEntityBean.entity.name.toFirstLower».get«m.property.name.toFirstUpper»(),
"«m.mimeType»",
blobAPI
);
«firstEntityBean.entity.name.toFirstLower».set«m.property.name.toFirstUpper»(«m.property.name.toFirstLower»Id);
} catch (IOException e) {
log.error(e.getLocalizedMessage());
}
'''
}
}
}
body = '''
«body»
em.getTransaction().begin();
if (log.isDebugEnabled()) log.debug("storing results");
«IF dataInterchange.mode==EntityManagerMode.PERSIST»em.persist(«firstEntityBean.entity.name.toFirstLower»);
«ELSEIF dataInterchange.mode==EntityManagerMode.MERGE»em.merge(«firstEntityBean.entity.name.toFirstLower»);
«ELSEIF dataInterchange.mode==EntityManagerMode.REMOVE»«firstEntityBean.entity.fullyQualifiedName» toBeRemoved = em.merge(«firstEntityBean.entity.name.toFirstLower»);
em.remove(toBeRemoved);«ENDIF»
if (log.isDebugEnabled()) log.debug("committing results");
em.getTransaction().commit();
'''
}
if (firstEntityBean.isMarkLatestImport) {
body = '''
«body»
if (log.isDebugEnabled()) log.debug("mark results as latest import");
em.setProperty(QueryHints.PESSIMISTIC_LOCK, PessimisticLock.Lock);
em.getTransaction().begin();
em.createQuery("update «firstEntityBean.entity.name» set «firstEntityBean.latestProperty.name» = 0").executeUpdate();
em.createQuery("update «firstEntityBean.entity.name» set «firstEntityBean.latestProperty.name» = 1 where id= :id").setParameter("id", «firstEntityBean.entity.name.toFirstLower».getId()).executeUpdate();
if (log.isDebugEnabled()) log.debug("committing mark");
em.getTransaction().commit();
'''
}
body = '''
«body»
if (log.isDebugEnabled()) log.debug("results persisted");
} else {
if (log.isDebugEnabled()) log.debug("no results found");
}
if(isDeleteFileAfterImport()){
deleteFile(Paths.get(getFileURL().getPath().substring(1))); // interchange file
}
'''
var root = dataInterchange.path.findFirst[!it.isMarkLatestImport]
if(root !== null) {
body = '''
«body»
} else {
if (log.isDebugEnabled()) log.debug("prepare export");
CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery<Long> countQuery = criteriaBuilder.createQuery(Long.class);
Root<«root.entity.fullyQualifiedName»> fr = countQuery.from(«root.entity.fullyQualifiedName».class);
countQuery«IF root.exportFilter !== null»«root.exportFilter.buildExportFilterWhereClause("fr")»«ENDIF».select(criteriaBuilder.count(fr));
Long count = em.createQuery(countQuery).getSingleResult();
CriteriaQuery<«root.entity.fullyQualifiedName»> criteriaQuery = criteriaBuilder.createQuery(«root.entity.fullyQualifiedName».class);
Root<«root.entity.fullyQualifiedName»> from = criteriaQuery.from(«root.entity.fullyQualifiedName».class);
«dataInterchange.buildJoins»
CriteriaQuery<«root.entity.fullyQualifiedName»> select = criteriaQuery.multiselect(from);
«IF root.exportFilter !== null»
select«root.exportFilter.buildExportFilterWhereClause("from")»;
«ENDIF»
TypedQuery<«root.entity.fullyQualifiedName»> typedQuery = em.createQuery(select);
setProgressIndeterminated(false);
List<«root.entity.fullyQualifiedName»> allResults = typedQuery.getResultList();
if (log.isDebugEnabled()) log.debug("evaluate root entity count");
setLength(count*«IF dataInterchange.elementSize==0»10«ELSE»«dataInterchange.elementSize»«ENDIF»);
setAvgElementSize(1);
if (log.isDebugEnabled()) log.debug("root entity count is "+count.toString());
StringWriter writer = new StringWriter();
if(dataInterchange != null) {
dataInterchange.exportSource(allResults, writer);
}
if(count > 0){ out.write(writer.toString().getBytes(«IF dataInterchange.fileEndpoint.encoding !== null»"«dataInterchange.fileEndpoint.encoding»"«ENDIF»));}
else{deleteFile(exportPath);}
«IF firstEntityBean.markLatestExport»
if(allResults != null && !allResults.isEmpty()){
CriteriaQuery cq = criteriaBuilder.createQuery();
Root<«root.entity.fullyQualifiedName»> fr1 = cq.from(«root.entity.fullyQualifiedName».class);
List<String> ids = em.createQuery(cq.select(fr1.get("«root.entity.idAttributeName»"))«IF root.exportFilter !== null»«root.exportFilter.buildExportFilterWhereClause("fr1")»«ENDIF»).getResultList();
if (log.isDebugEnabled()) log.debug("mark results as latest export");
em.setProperty(QueryHints.PESSIMISTIC_LOCK, PessimisticLock.Lock);
em.getTransaction().begin();
em.createQuery("update «firstEntityBean.entity.name» set «firstEntityBean.latestExpProperty.name» = 1 where «root.entity.idAttributeName» in :ids").setParameter("ids", ids).executeUpdate();
if (log.isDebugEnabled()) log.debug("committing mark export");
em.getTransaction().commit();
}
«ENDIF»
if (log.isDebugEnabled()) log.debug("export finished");
}
log.info(getDirection().name()+" of «dataInterchange.name» successfully ended!");
'''
} else {
body = '''
«body»
}'''
}
for (path:dataInterchange.path) {
var entity = path.entity
body = '''
«body»
if(getEventDispatcher() != null) {
EventDispatcherEvent «entity.name.toLowerCase»Event = new EventDispatcherEvent(EventDispatcherCommand.REFRESH, "«entity.fullyQualifiedName»", "«dataInterchange.fullyQualifiedName»");
getEventDispatcher().sendEvent(«entity.name.toLowerCase»Event);
}
'''
}
body = '''
«body»
} catch (DataInterchangeException | IllegalArgumentException | IOException e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
log.error(getDirection().name()+" Execution of «dataInterchange.name»: failed due to: {}", sw.toString());
setExecutionFailed(true);
} finally {
if(file != null) {
try {
out.close();
file.close();
} catch (IOException e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
log.error("«dataInterchange.name»:{}", sw.toString());
}
}
if(dataInterchange != null) {
dataInterchange.close();
}
if (em != null) {
em.close();
}
// remove progress bar
if(getEventDispatcher() != null) {
EventDispatcherEvent evnt = new EventDispatcherEvent(EventDispatcherCommand.FINISHED, getName(), "DataInterchangeWorkerThread");
getEventDispatcher().sendEvent(evnt);
}
if (log.isDebugEnabled()) log.debug("datainterchange finished");
}
'''
return body
}
/**
* handle the worker progress bar. provide the appropriate code.
*
* @return code fragment
*/
def String removeProgressBar() {
var body = ""
body = '''
«body»
// a worker notified this view that it is finished
if (progressBars.containsKey(workerName)) {
final WorkerThreadRunnable worker = progressBars.get(workerName);
((VerticalLayout)worker.getProgressBarArea().getParent()).removeComponent(worker.getProgressBarArea());
progressBars.remove(workerName);
}
'''
return body
}
def localeChanged(DataInterchangeGroup group)
'''
if(logo != null) {
logo.setValue(dslMetadataService.translate(locale.toLanguageTag(), "«group.name»"));
}
if(buttons != null) {
for(Button button: buttons.keySet()) {
ArrayList i18nKeys = buttons.get(button);
button.setDescription(dslMetadataService.translate(locale.toLanguageTag(),(String)i18nKeys.get(0))+" "+dslMetadataService.translate(locale.toLanguageTag(),(String)i18nKeys.get(2)));
}
for(Panel panel:panels.keySet()){
ArrayList i18nKeys = panels.get(panel);
panel.setCaption(dslMetadataService.translate(locale.toLanguageTag(),(String)i18nKeys.get(1)));
}
}'''
def String receiveEvent() {
var body = ""
body = '''
«body»
switch(event.getCommand()) {
case FINISHED:
removeProgressBar(event.getTopic());
break;
}
'''
return body
}
def String buildExportFilterWhereClause(DataInterchangeExportFilter excludes, String rootname){
var body = ""
if(excludes!==null){
var where = excludes.getCondition.buildSubCondition(rootname)
if(where !== null && !where.empty){
body = '''.where(«where»)'''
}
}
return body
}
def String buildSubCondition(DataInterchangeFilterCondition condition, String rootname){
var part1 = ""
if(condition !== null && condition.getOperator !== null){
switch(condition.getOperator){
case ISNOTNULL:
part1 = '''«rootname».get("«condition.getRefProperty.name»").isNotNull()'''
case ISNULL:
part1 = '''«rootname».get("«condition.getRefProperty.name»").isNull()'''
case EQUALS:
if(condition.getValue !== null && !condition.getValue.empty){
part1 = '''criteriaBuilder.equal(«rootname».get("«condition.getRefProperty.name»"), "«condition.getValue»")'''
}
else{ part1 = null}
case NOTEQUALS:
if(condition.getValue !== null && !condition.getValue.empty){
part1 = '''criteriaBuilder.notEqual(«rootname».get("«condition.getRefProperty.name»"), "«condition.getValue»")'''
}
else{ part1 = null}
case GREATERTHEN:
if(condition.getValue !== null && !condition.getValue.empty){
part1 = '''criteriaBuilder.greaterThan(«rootname».get("«condition.getRefProperty.name»"), "«condition.getValue»")'''
}
else{ part1 = null}
case GREATERTHENOREQUALTO:
if(condition.getValue !== null && !condition.getValue.empty){
part1 = '''criteriaBuilder.greaterThanOrEqualTo(«rootname».get("«condition.getRefProperty.name»"), "«condition.getValue»")'''
}
else{ part1 = null}
case LESSTHEN:
if(condition.getValue !== null && !condition.getValue.empty){
part1 = '''criteriaBuilder.lessThan(«rootname».get("«condition.getRefProperty.name»"), "«condition.getValue»")'''
}
else{ part1 = null}
case LESSTHENOREQUALTO:
if(condition.getValue !== null && !condition.getValue.empty){
part1 = '''criteriaBuilder.lessThanOrEqualTo(«rootname».get("«condition.getRefProperty.name»"), "«condition.getValue»")'''
}
else{ part1 = null}
default: { part1 = null }
}
if(part1 !== null && condition.getOperator2 !== null && condition.getSubcondition !== null ){
switch(condition.getOperator2){
case AND: return '''criteriaBuilder.and(«part1» , «condition.getSubcondition.buildSubCondition(rootname)» )'''
case OR : return '''criteriaBuilder.or(«condition.getSubcondition.buildSubCondition(rootname)» , «part1»)'''
default: {return part1 }
}
}
}
return part1
}
/**
* build a graph for all entities in path
*/
def buildJoins(DataInterchange interchange) {
val joinGraph = new JoinGraph<LEntity>
// add all entities as nodes that are not indicators for last imported
interchange.path.filter[!it.isMarkLatestImport].forEach[joinGraph.addNode(it.entity)]
// add all possible oneToMany relations between the given entities
interchange.path.filter[!it.isMarkLatestImport].forEach[
val source = it.entity
// do not test relations with itself
interchange.path.filter[!it.entity.equals(source)].forEach[
val dest = it.entity
// get only references of type oneToMany where source and destination match
source.features.filter[
ref|ref instanceof LReference && ref.toMany && ref.type instanceof LEntity && ref.type.toName.equals(dest.toName)
].forEach[ref|
// add the join with name that was found
joinGraph.addJoin(source, dest, ref.name)
]
]
]
// calculate all possible paths of the given path
var joinManager = new ManageJoins<LEntity>(joinGraph);
var joins = joinManager.getAllJoins(interchange.path.findFirst[!it.isMarkLatestImport].entity)
// create join commands for criterabuilder if path not empty
val output = new StringBuilder
joins.filter[!it.empty].forEach[path|
output.append("from")
path.forEach[join|
output.append('''.fetch("«join»", JoinType.LEFT)''')
]
output.append(";\n")
]
return output.toString
}
}