blob: 344f957c386e9982a715915b17bb8559afed2431 [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.vaadin.server.ClientConnector.AttachEvent
import com.vaadin.server.ClientConnector.AttachListener
import com.vaadin.server.ClientConnector.DetachEvent
import com.vaadin.server.ClientConnector.DetachListener
import com.vaadin.ui.Button
import com.vaadin.ui.CssLayout
import com.vaadin.ui.Label
import com.vaadin.ui.VerticalLayout
import java.io.OutputStream
import java.net.URL
import java.util.ArrayList
import java.util.HashMap
import java.util.Locale
import java.util.Map
import java.util.concurrent.ExecutorService
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.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.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.DataInterchangeFileCSV
import org.eclipse.osbp.xtext.datainterchange.DataInterchangeFileEDI
import org.eclipse.osbp.xtext.datainterchange.DataInterchangeFileXML
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.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
import org.eclipse.osbp.ui.api.customfields.IBlobService
/**
* <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 dataInterchangePackage
* An instance of {@link DataInterchangePackage}
* @param acceptor
* the xtext acceptor interface
* @param isPreIndexingPhase
* true if in preindexing phase
*/
def dispatch void infer(DataInterchangePackage dataInterchangePackage, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
dataInterchangePackage.generatePckgName(acceptor)
// create a view
var cls = dataInterchangePackage.toClass(dataInterchangePackage.name.toString.concat("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(DetachListener)
superTypes += _typeReferenceBuilder.typeRef(AttachListener)
superTypes += _typeReferenceBuilder.typeRef(IE4Focusable)
packageName = dataInterchangePackage.fullyQualifiedName.toString
it.fileHeader = dataInterchangePackage.documentation
it.toFields(dataInterchangePackage)
it.toConstructor(dataInterchangePackage)
it.toOperations(dataInterchangePackage)
])
// create classes
for (dataInterchange : dataInterchangePackage.datInts) {
var clsName2 = dataInterchange.fullyQualifiedName
acceptor.accept(dataInterchange.toClass(clsName2),
[
superTypes += _typeReferenceBuilder.typeRef(WorkerThreadRunnable)
annotations += _annotationTypesBuilder.annotationRef(SuppressWarnings, "serial")
it.fileHeader = dataInterchangePackage.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, DataInterchangePackage pkg) {
var JvmField field = null
field = pkg.toField("sidebar", _typeReferenceBuilder.typeRef(VerticalLayout))
type.members += field
field = pkg.toField("log", _typeReferenceBuilder.typeRef(Logger)) [setInitializer([ append('''LoggerFactory.getLogger(«pkg.fullyQualifiedName.lastSegment.toFirstUpper»TriggerView.class)''') ])]
field.final = true
field.static = true
type.members += field
field = pkg.toField("menu", _typeReferenceBuilder.typeRef(CssLayout))
type.members += field
field = pkg.toField("branding", _typeReferenceBuilder.typeRef(CssLayout))
type.members += field
field = pkg.toField("persistenceService", _typeReferenceBuilder.typeRef(IPersistenceService)) [
annotations += _annotationTypesBuilder.annotationRef(Inject)
]
type.members += field
field = pkg.toField("progressBars", _typeReferenceBuilder.typeRef(Map, _typeReferenceBuilder.typeRef(String), _typeReferenceBuilder.typeRef(WorkerThreadRunnable)))
type.members += field
field = pkg.toField("executorService", _typeReferenceBuilder.typeRef(ExecutorService))
field.static = true
type.members += field
field = pkg.toField("dslMetadataService", _typeReferenceBuilder.typeRef(IDSLMetadataService)) [annotations += _annotationTypesBuilder.annotationRef(Inject)]
type.members += field
field = pkg.toField("dataInterchange", _typeReferenceBuilder.typeRef(IDataInterchange)) [annotations += _annotationTypesBuilder.annotationRef(Inject)]
type.members += field
field = pkg.toField("eventDispatcher", _typeReferenceBuilder.typeRef(IEventDispatcher))[annotations += _annotationTypesBuilder.annotationRef(Inject)]
type.members += field
field = pkg.toField("blobService", _typeReferenceBuilder.typeRef(IBlobService))[annotations += _annotationTypesBuilder.annotationRef(Inject)]
type.members += field
field = pkg.toField("user", _typeReferenceBuilder.typeRef(IUser))[annotations += _annotationTypesBuilder.annotationRef(Inject)]
type.members += field
field = pkg.toField("logo", _typeReferenceBuilder.typeRef(Label))
type.members += field
field = pkg.toField("buttons",
_typeReferenceBuilder.typeRef(HashMap, _typeReferenceBuilder.typeRef(Button), _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, DataInterchangePackage pkg) {
type.members += pkg.toConstructor([
annotations += _annotationTypesBuilder.annotationRef(Inject)
parameters += pkg.toParameter("parent", _typeReferenceBuilder.typeRef(VerticalLayout))
parameters += pkg.toParameter("context", _typeReferenceBuilder.typeRef(IEclipseContext))
parameters += pkg.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, DataInterchangePackage pkg) {
// create view
type.members += pkg.toMethod("createView", _typeReferenceBuilder.typeRef(Void::TYPE), [
parameters += pkg.toParameter("parent", _typeReferenceBuilder.typeRef(VerticalLayout))
body = [ append('''«pkg.createView»''')]
])
// create components
type.members += pkg.toMethod("createComponents", _typeReferenceBuilder.typeRef(Void::TYPE), [
body = [ append('''«pkg.createComponents»''')]
])
// is duplicate
type.members += pkg.toMethod("isDuplicate", _typeReferenceBuilder.typeRef(boolean), [
parameters += pkg.toParameter("name", _typeReferenceBuilder.typeRef(String))
body = [ append('''«pkg.isDuplicate»''')]
])
// find layout
type.members += pkg.toMethod("findButtonLayout", _typeReferenceBuilder.typeRef(VerticalLayout), [
parameters += pkg.toParameter("button", _typeReferenceBuilder.typeRef(Button))
body = [ append('''«pkg.findButtonLayout»''')]
])
// remove progressbar
type.members += pkg.toMethod("removeProgressBar", _typeReferenceBuilder.typeRef(Void::TYPE), [
parameters += pkg.toParameter("workerName", _typeReferenceBuilder.typeRef(String))
body = [ append('''«pkg.removeProgressBar»''')]
])
// on bundle stopping - shutdown executorService
type.members += pkg.toMethod("bundleChanged", _typeReferenceBuilder.typeRef(Void::TYPE), [
annotations += _annotationTypesBuilder.annotationRef(Override)
parameters += pkg.toParameter("event", _typeReferenceBuilder.typeRef(BundleEvent))
body = [ append('''«pkg.bundleChanged»''')]
])
// attach
type.members += pkg.toMethod("attach", _typeReferenceBuilder.typeRef(Void::TYPE),
[
parameters += pkg.toParameter("event", _typeReferenceBuilder.typeRef(AttachEvent))
annotations += _annotationTypesBuilder.annotationRef(Override)
body = [append(
'''
user.addUserLocaleListener(this);
eventDispatcher.addEventReceiver(this);''')]
])
// detach
type.members += pkg.toMethod("detach", _typeReferenceBuilder.typeRef(Void::TYPE),
[
parameters += pkg.toParameter("event", _typeReferenceBuilder.typeRef(DetachEvent))
annotations += _annotationTypesBuilder.annotationRef(Override)
body = [append(
'''
user.removeUserLocaleListener(this);
eventDispatcher.removeEventReceiver(this);''')]
])
// focus
type.members += pkg.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 += pkg.toMethod("localeChanged", _typeReferenceBuilder.typeRef(Void::TYPE),
[
visibility = JvmVisibility.PUBLIC
annotations += _annotationTypesBuilder.annotationRef(Override)
parameters += pkg.toParameter("locale", _typeReferenceBuilder.typeRef(Locale))
body = [append('''«pkg.localeChanged»''')]
])
// event notification
type.members += pkg.toMethod("receiveEvent", _typeReferenceBuilder.typeRef(Void::TYPE),
[
visibility = JvmVisibility.PUBLIC
annotations += _annotationTypesBuilder.annotationRef(Override)
parameters += pkg.toParameter("event", _typeReferenceBuilder.typeRef(EventDispatcherEvent))
body = [append('''«pkg.receiveEvent»''')]
])
}
/**
* let the app wait for finishing the workers before allowing to stop bundle.
*
* @param pkg
* the current package inferred {@link DataInterchangePackage}
* @return code fragment
*/
def String bundleChanged(DataInterchangePackage pkg) {
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.
*
* @param pkg
* the current package inferred {@link DataInterchangePackage}
* @return code fragment
*/
def String findButtonLayout(DataInterchangePackage pkg) {
var body = ""
body = '''
«body»
int count = menu.getComponentCount();
for(int i=0; i<count; i++) {
VerticalLayout buttonLayout = (VerticalLayout)menu.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.
*
* @param pkg
* the current package inferred {@link DataInterchangePackage}
* @return code fragment
*/
def String isDuplicate(DataInterchangePackage pkg) {
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(DataInterchangePackage pkg) {
var body = '''
getContext().set(IE4Focusable.class, this);
parent.addAttachListener(this);
parent.addDetachListener(this);
buttons = 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();
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
sidebar.addComponent(menu);
sidebar.setExpandRatio(menu, 1.0f);
'''
body = '''
«body»
// add menu items
Button b;
VerticalLayout buttonLayout;
'''
for (dataInterchange : pkg.datInts) {
body = '''
«body»
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);
menu.addComponent(buttonLayout);
'''
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);
menu.addComponent(buttonLayout);
'''
}
body = '''
«body»
menu.addStyleName("menu");
menu.setHeight("100%");
'''
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 = dataInterchange.fullyQualifiedName.toString
}
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 DataInterchangePackage).title»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);
'''
}
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 ""
}
/**
* create more components. this fragment is repainted if something changes (e.g. language)
*
* @param pkg
* the current package inferred {@link DataInterchangePackage}
* @return code fragment
*/
def String createComponents(DataInterchangePackage pkg) {
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("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»''')]
])
}
/**
* <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 {
Path path = null;
path = Paths.get(uri);
try {
// find a unique name - similar to given
file = Files.newOutputStream(path, 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 {
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.markLatest»List«ENDIF»"«IF dataInterchange.fileEndpoint.encoding !== null», "«dataInterchange.fileEndpoint.encoding»"«ENDIF»);
if (log.isDebugEnabled()) log.debug("filtering finished");
'''
if (!firstEntityBean.markLatest) {
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;
'''
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.markLatest) {
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();
'''
}
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»
if (log.isDebugEnabled()) log.debug("results persisted");
} else {
if (log.isDebugEnabled()) log.debug("no results found");
}
'''
var root = dataInterchange.path.findFirst[it|!it.markLatest]
if(root !== null) {
body = '''
«body»
} else {
if (log.isDebugEnabled()) log.debug("prepare export");
CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
if (log.isDebugEnabled()) log.debug("evaluate root entity count");
CriteriaQuery<Long> countQuery = criteriaBuilder.createQuery(Long.class);
countQuery.select(criteriaBuilder.count(countQuery.from(«root.entity.fullyQualifiedName».class)));
Long count = em.createQuery(countQuery).getSingleResult();
if (log.isDebugEnabled()) log.debug("root entity count is "+count.toString());
setLength(count*«IF dataInterchange.elementSize==0»10«ELSE»«dataInterchange.elementSize»«ENDIF»);
setAvgElementSize(1);
CriteriaQuery<«root.entity.fullyQualifiedName»> criteriaQuery = criteriaBuilder.createQuery(«root.entity.fullyQualifiedName».class);
Root<«root.entity.fullyQualifiedName»> from = criteriaQuery.from(«root.entity.fullyQualifiedName».class);
CriteriaQuery<«root.entity.fullyQualifiedName»> select = criteriaQuery.multiselect(from);
TypedQuery<«root.entity.fullyQualifiedName»> typedQuery = em.createQuery(select);
setProgressIndeterminated(false);
List<«root.entity.fullyQualifiedName»> allResults = typedQuery.getResultList();
StringWriter writer = new StringWriter();
if(dataInterchange != null) {
dataInterchange.exportSource(allResults, writer);
}
out.write(writer.toString().getBytes());
if (log.isDebugEnabled()) log.debug("export finished");
}
'''
} else {
body = '''
«body»
}'''
}
body = '''
«body»
} catch (DataInterchangeException | IOException e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
log.error("«dataInterchange.name»:{}", sw.toString());
} 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.REMOVE_PROGRESSBAR, getName(), "DataInterchangeWorkerThread");
getEventDispatcher().sendEvent(evnt);
}
if (log.isDebugEnabled()) log.debug("datainterchange finished");
}
'''
return body
}
/**
* handle the worker progress bar. provide the appropriate code.
*
* @param pkg
* the current package inferred {@link DataInterchangePackage}
* @return code fragment
*/
def String removeProgressBar(DataInterchangePackage pkg) {
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(DataInterchangePackage pkg)
'''
«IF pkg.title != null»
if(logo != null) {
logo.setValue(dslMetadataService.translate(locale.toLanguageTag(), "«pkg.title»"));
}
«ENDIF»
if(buttons != null) {
for(Button button: buttons.keySet()) {
ArrayList i18nKeys = buttons.get(button);
button.setCaption(dslMetadataService.translate(locale.toLanguageTag(),(String)i18nKeys.get(1)));
button.setDescription(dslMetadataService.translate(locale.toLanguageTag(),(String)i18nKeys.get(0))+" "+dslMetadataService.translate(locale.toLanguageTag(),(String)i18nKeys.get(2)));
}
}'''
def String receiveEvent(DataInterchangePackage pkg) {
var body = ""
body = '''
«body»
switch(event.getCommand()) {
case REMOVE_PROGRESSBAR:
removeProgressBar(event.getTopic());
break;
}
'''
return body
}
}