diff options
author | Ralf Mollik | 2017-08-28 15:40:12 +0000 |
---|---|---|
committer | Ralf Mollik | 2017-08-28 15:40:12 +0000 |
commit | 5242629acf3fa3f994ef12e40e21006ecf2d4114 (patch) | |
tree | 57f3a4a0466bc6f10608df82f839592ffcec7c81 /org.eclipse.osbp.xtext.datainterchange/src/org/eclipse | |
download | org.eclipse.osbp.xtext.datainterchange-5242629acf3fa3f994ef12e40e21006ecf2d4114.tar.gz org.eclipse.osbp.xtext.datainterchange-5242629acf3fa3f994ef12e40e21006ecf2d4114.tar.xz org.eclipse.osbp.xtext.datainterchange-5242629acf3fa3f994ef12e40e21006ecf2d4114.zip |
parallel ip - initial checkin
Signed-off-by: Ralf Mollik <ramollik@compex-commerce.com>
Diffstat (limited to 'org.eclipse.osbp.xtext.datainterchange/src/org/eclipse')
15 files changed, 3075 insertions, 0 deletions
diff --git a/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/Activator.java b/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/Activator.java new file mode 100644 index 0000000..9e91749 --- /dev/null +++ b/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/Activator.java @@ -0,0 +1,47 @@ +/** + * + * 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 + * + */ + package org.eclipse.osbp.xtext.datainterchange; + + +import org.eclipse.osbp.gitinfo.Loginfo; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +public class Activator implements BundleActivator { + + private static BundleContext context; + + static BundleContext getContext() { + return context; + } + + /* + * (non-Javadoc) + * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext) + */ + public void start(BundleContext bundleContext) throws Exception { + Activator.context = bundleContext; + Loginfo li = new Loginfo(); + li.print( Activator.class.getCanonicalName(), Activator.class.getClassLoader()); + } + + /* + * (non-Javadoc) + * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) + */ + public void stop(BundleContext bundleContext) throws Exception { + Activator.context = null; + } + +} diff --git a/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/DataDSL.xtext b/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/DataDSL.xtext new file mode 100644 index 0000000..16f1808 --- /dev/null +++ b/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/DataDSL.xtext @@ -0,0 +1,142 @@ +/** + * + * 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 + * + */ + +grammar org.eclipse.osbp.xtext.datainterchange.DataDSL with org.eclipse.xtext.xbase.annotations.XbaseWithAnnotations + +import "http://osbp.eclipse.org/xtext/datainterchange/DataDSL" + +import "http://osbp.eclipse.org/dsl/common/types/v1" as types +import "http://osbp.eclipse.org/dsl/entity/v1" as entity +import "http://www.eclipse.org/emf/2002/Ecore" as ecore + +DataInterchangeModel: + packages+=DataInterchangePackage*; + +DataInterchangePackage: + {DataInterchangePackage} 'package' name=QualifiedName 'title' title=TRANSLATABLESTRING + ('{' (imports+=DataInterchangeImport)* (datInts+=DataInterchange)* '}' )?; + +DataInterchange: + {DataInterchange} 'interchange' name=TRANSLATABLEID + (description?='described by' descriptionValue=TRANSLATABLESTRING)? + (createReport?='create report')? + ('averageElementSize' elementSize=INT)? + ('progressBarStyle' progressBarStyle=ProgressBarStylesEnum)? + (refreshEnabled?='refreshViewWhenFinished' refresh=STRING)? + 'file' fileEndpoint=DataInterchangeFile 'beans' '{' (path+=DataInterchangeBean)* '}'; + +DataInterchangeFile: + DataInterchangeFileXML | DataInterchangeFileCSV | DataInterchangeFileEDI; + +DataInterchangeFileXML: + {DataInterchangeFileXML} 'XML' fileURL=STRING; + +DataInterchangeFileCSV: + {DataInterchangeFileCSV} 'CSV' fileURL=STRING + ( + ('delimiter' delimiter=STRING)? & ('quoteCharacter' quoteCharacter=STRING)? & ('skipLines' skipLines=INT)? & + (indent?='indent')? & (strict?='strict')? & (validateHeader?='validateHeader')? & ('encoding' encoding=STRING)? + ); + +DataInterchangeFileEDI: + {DataInterchangeFileEDI} 'EDI' fileURL=STRING 'mappingModel' mappingModel=STRING (validate?='validate')?; + +DataInterchangeBean: + {DataInterchangeBean} + 'entity' entity=[entity::LEntity|LFQN] + ('createOn' elementMap=STRING)? + (markLatest?='marker' latestProperty=[entity::LEntityAttribute])? + ((recordElement?='recordElement') | + (recordList?='recordList'))? + ('expression' '{' (expression+=DataInterchangeExpression)* '}')? + ('lookup' '{' (lookup+=DataInterchangeLookup)* '}')? + ('format' '{' (format+=DataInterchangeFormat)* '}')? + ('mapping' '{' (mappings+=DataInterchangeMapping)* '}')? + ; + +DataInterchangeLookup: + {DataInterchangeLookup} + 'for' targetProperty=[entity::LEntityReference] + 'on' entity=[entity::LEntity] + ('createOn' elementMap=STRING)? + 'with' queryProperty=[entity::LEntityAttribute] + (cached?='cacheSize' cacheSize=INT)? + ('mapTo' dataMap=STRING)? + ( + (allowNoResult?='allowNoResult')? & + (allowNonuniqueResult?='allowNonuniqueResult')? & + (markerPath=DataInterchangeMarkerPath)? + ); + +DataInterchangeMarkerPath: + {DataInterchangeMarkerPath} + 'markerPath' '{' (path+=DataInterchangeMarkerEntity)* '}'; + +DataInterchangeMarkerEntity: + {DataInterchangeMarkerEntity} + 'markerEntity' markerEntity=[entity::LEntity|LFQN] + (markLatest?='markedBy' markerProperty=[entity::LEntityAttribute])?; + +DataInterchangeFormat: + {DataInterchangeFormat} 'for' targetProperty=[entity::LEntityAttribute] 'coding' format=STRING ('locale' locale=STRING)?; + +DataInterchangeExpression: + DataInterchangeEntityExpression | DataInterchangePredefinedExpression; + +DataInterchangeEntityExpression: + {DataInterchangeEntityExpression} 'copy' targetProperty=[entity::LEntityAttribute] 'from' entity=[entity::LEntity|LFQN] 'property' property=[entity::LEntityAttribute]; + +DataInterchangePredefinedExpression: + {DataInterchangePredefinedExpression} 'assign' targetProperty=[entity::LEntityAttribute] 'with' bean=PredefinedBeanEnum 'as' beanType=PredefinedBeanTypeEnum; + +DataInterchangeMapping: + {DataInterchangeMapping} 'map' property=[entity::LEntityAttribute] 'to' data=STRING; + +DataInterchangeImport returns types::LImport: +'import' importedNamespace=DataInterchangeQualifiedNameWithWildCard; + +DataInterchangeQualifiedNameWithWildCard: + QualifiedName ('.' '*')?; + +QualifiedName: + ValidID (=>'.' ValidID)*; + +ValidID: + ID; + +LFQN: + ID ('.' ID)*; + +TRANSLATABLESTRING: + STRING; + +TRANSLATABLEID: + ID; + +enum PredefinedBeanEnum: + now = 'NowDate'| + start = 'StartDate'| + UUID = 'UniversallyUniqueIdentifier'; + +enum PredefinedBeanTypeEnum: + Date = 'Date'| + Millis = 'Milliseconds'| + Nanos = 'Nanoseconds'| + random = 'Random'| + execContext = 'ExecuteContext'; + +enum ProgressBarStylesEnum: + none = 'none'| + normal = 'normal'| + important = 'important'; diff --git a/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/DataDSLBundleSpaceRuntimeModule.java b/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/DataDSLBundleSpaceRuntimeModule.java new file mode 100644 index 0000000..4efabf9 --- /dev/null +++ b/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/DataDSLBundleSpaceRuntimeModule.java @@ -0,0 +1,42 @@ +/** + * + * 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 + * + */ + package org.eclipse.osbp.xtext.datainterchange; + +import org.eclipse.osbp.dsl.xtext.types.bundles.BundleSpaceTypeProviderFactory; +import org.eclipse.osbp.dsl.xtext.types.bundles.BundleSpaceTypeScopeProvider; +import org.eclipse.osbp.xtext.builder.types.loader.api.ITypeLoaderFactory; +import org.eclipse.osbp.xtext.builder.types.loader.api.ITypeLoaderProvider; +import org.eclipse.osbp.xtext.builder.types.loader.runtime.TypeLoaderFactory; +import org.eclipse.osbp.xtext.builder.types.loader.runtime.TypeLoaderProvider; + +@SuppressWarnings("restriction") +public class DataDSLBundleSpaceRuntimeModule extends DataDSLRuntimeModule { + // contributed by org.eclipse.xtext.generator.types.TypesGeneratorFragment + public Class<? extends org.eclipse.xtext.common.types.access.IJvmTypeProvider.Factory> bindIJvmTypeProvider$Factory() { + return BundleSpaceTypeProviderFactory.class; + } + + // contributed by org.eclipse.xtext.generator.types.TypesGeneratorFragment + public Class<? extends org.eclipse.xtext.common.types.xtext.AbstractTypeScopeProvider> bindAbstractTypeScopeProvider() { + return BundleSpaceTypeScopeProvider.class; + } + + public Class<? extends ITypeLoaderFactory> bindITypeLoaderFactory() { + return TypeLoaderFactory.class; + } + + public Class<? extends ITypeLoaderProvider> ITypeLoaderProvider() { + return TypeLoaderProvider.class; + } +} diff --git a/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/DataDSLBundleSpaceStandaloneSetup.java b/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/DataDSLBundleSpaceStandaloneSetup.java new file mode 100644 index 0000000..0908fa6 --- /dev/null +++ b/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/DataDSLBundleSpaceStandaloneSetup.java @@ -0,0 +1,40 @@ +/** + * + * 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 + * + */ + package org.eclipse.osbp.xtext.datainterchange; + +import org.eclipse.osbp.xtext.builder.xbase.setups.XbaseBundleSpaceStandaloneSetup; + +import com.google.inject.Guice; +import com.google.inject.Injector; + +@SuppressWarnings("restriction") +public class DataDSLBundleSpaceStandaloneSetup extends DataDSLStandaloneSetup { + public static void doSetup() { + new DataDSLBundleSpaceStandaloneSetup().createInjectorAndDoEMFRegistration(); + } + + @Override + public Injector createInjectorAndDoEMFRegistration() { + XbaseBundleSpaceStandaloneSetup.doSetup(); + + Injector injector = createInjector(); + register(injector); + return injector; + } + + @Override + public Injector createInjector() { + return Guice.createInjector(new DataDSLBundleSpaceRuntimeModule()); + } +} diff --git a/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/DataDSLRuntimeModule.java b/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/DataDSLRuntimeModule.java new file mode 100644 index 0000000..461b754 --- /dev/null +++ b/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/DataDSLRuntimeModule.java @@ -0,0 +1,77 @@ +/** + * + * 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 + * + */ + package org.eclipse.osbp.xtext.datainterchange; + +import javax.inject.Singleton; + +import org.eclipse.xtext.conversion.IValueConverterService; +import org.eclipse.xtext.generator.IGenerator; +import org.eclipse.xtext.generator.IOutputConfigurationProvider; +import org.eclipse.xtext.naming.IQualifiedNameProvider; +import org.eclipse.xtext.scoping.IScopeProvider; +import org.eclipse.osbp.dsl.xtext.lazyresolver.LazyJvmTypeLinker; +import org.eclipse.osbp.dsl.xtext.lazyresolver.SemanticLoadingResource; +import org.eclipse.osbp.dsl.xtext.lazyresolver.linker.LazyJvmTypeTransientValueService; + +import com.google.inject.Binder; + +import org.eclipse.osbp.xtext.datainterchange.jvmmodel.DataDSLModelGenerator; +import org.eclipse.osbp.xtext.datainterchange.scoping.DataDSLScopeProvider; +import org.eclipse.osbp.xtext.datainterchange.valueconverter.DataDSLQualifiedNameProvider; +import org.eclipse.osbp.xtext.datainterchange.valueconverter.DataDSLValueConverterService; +import org.eclipse.osbp.xtext.i18n.DSLOutputConfigurationProvider; + +/** + * Use this class to register components to be used at runtime / without the Equinox extension registry. + */ +public class DataDSLRuntimeModule extends org.eclipse.osbp.xtext.datainterchange.AbstractDataDSLRuntimeModule { + @Override + public Class<? extends IGenerator> bindIGenerator() { + return DataDSLModelGenerator.class; + } + + @Override + public Class<? extends IScopeProvider> bindIScopeProvider() { + return DataDSLScopeProvider.class; + } + + @Override + public Class<? extends IQualifiedNameProvider> bindIQualifiedNameProvider() { + return DataDSLQualifiedNameProvider.class; + } + + @Override + public Class<? extends IValueConverterService> bindIValueConverterService() { + return DataDSLValueConverterService.class; + } + + @Override + public void configure(Binder binder) { + super.configure(binder); + binder.bind(IOutputConfigurationProvider.class).to(DSLOutputConfigurationProvider.class).in(Singleton.class); + } + + public Class<? extends org.eclipse.xtext.resource.XtextResource> bindXtextResource() { + return SemanticLoadingResource.class; + } + + public Class<? extends org.eclipse.xtext.linking.ILinker> bindILinker() { + return LazyJvmTypeLinker.class; + } + + public Class<? extends org.eclipse.xtext.serializer.sequencer.ITransientValueService> bindSerializerITransientValueService() { + return LazyJvmTypeTransientValueService.class; + } + +} diff --git a/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/DataDSLStandaloneSetup.java b/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/DataDSLStandaloneSetup.java new file mode 100644 index 0000000..385a19b --- /dev/null +++ b/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/DataDSLStandaloneSetup.java @@ -0,0 +1,26 @@ +/** + * + * 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 + * + */ + package org.eclipse.osbp.xtext.datainterchange; + +/** + * Initialization support for running Xtext languages + * without equinox extension registry + */ +public class DataDSLStandaloneSetup extends DataDSLStandaloneSetupGenerated{ + + public static void doSetup() { + new DataDSLStandaloneSetup().createInjectorAndDoEMFRegistration(); + } +} + diff --git a/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/GenerateDataDSL.mwe2 b/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/GenerateDataDSL.mwe2 new file mode 100644 index 0000000..1b9f021 --- /dev/null +++ b/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/GenerateDataDSL.mwe2 @@ -0,0 +1,164 @@ +/** + * + * 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 + * + */ +module org.eclipse.osbp.xtext.datainterchange.GenerateDataDSL + +import org.eclipse.emf.mwe.utils.* +import org.eclipse.xtext.generator.* +import org.eclipse.xtext.ui.generator.* +import org.eclipse.osbp.dsl.mwe.* + +var projectName = "org.eclipse.osbp.xtext.datainterchange" +var grammarURI = "platform:/resource/${projectName}/src/org/eclipse/osbp/xtext/datainterchange/DataDSL.xtext" +var fileExtensions = "data" +var runtimeProject = "../${projectName}" +var generateXtendStub = true +var encoding = "UTF-8" + +Workflow { + bean = org.eclipse.emf.ecore.xcore.XcoreStandaloneSetup : xcore {} + bean = org.eclipse.xtext.mwe.Reader { + register = xcore + } + bean = MavenStandaloneSetup { + scanClassPath = true + platformUri = "${runtimeProject}/.." + registerGenModelFile = "platform:/resource/org.eclipse.osbp.xtext.datainterchange/model/DataDSL.xcore" +// registerEcoreFile = "platform:/resource/org.eclipse.osbp.xtext.datainterchange/model/DataDSL.xcore" + registerGeneratedEPackage = "org.eclipse.osbp.xtext.datainterchange.DataDSLPackage" + + registerGenModelFile = "platform:/resource/org.eclipse.osbp.dsl.entity.xtext/model/entity.xcore" +// registerEcoreFile = "platform:/resource/org.eclipse.osbp.dsl.entity.xtext/model/entity.xcore" + + registerGenModelFile = "platform:/resource/org.eclipse.osbp.dsl.common.xtext/model/types.xcore" +// registerEcoreFile = "platform:/resource/org.eclipse.osbp.dsl.common.xtext/model/types.xcore" + + registerGenModelFile = "platform:/resource/org.eclipse.xtext.common.types/model/JavaVMTypes.genmodel" + registerEcoreFile = "platform:/resource/org.eclipse.xtext.common.types/model/JavaVMTypes.ecore" + + registerGenModelFile = "platform:/resource/org.eclipse.xtext.xbase/model/Xbase.genmodel" + registerEcoreFile = "platform:/resource/org.eclipse.xtext.xbase/model/Xtype.ecore" + registerEcoreFile = "platform:/resource/org.eclipse.xtext.xbase/model/Xbase.ecore" + registerEcoreFile = "platform:/resource/org.eclipse.xtext.xbase/model/XAnnotations.ecore" + } + + component = DirectoryCleaner { + directory = "${runtimeProject}/src-gen" + exclude = "README.txt" + } + + component = DirectoryCleaner { + directory = "${runtimeProject}.ui/src-gen" + exclude = "README.txt" + } + + component = DirectoryCleaner { + directory = "${runtimeProject}.tests/src-gen" + exclude = "README.txt" + } + + component = Generator { + pathRtProject = runtimeProject + pathUiProject = "${runtimeProject}.ui" + pathTestProject = "${runtimeProject}.tests" + projectNameRt = projectName + projectNameUi = "${projectName}.ui" + encoding = encoding + language = auto-inject { + uri = grammarURI + + // Java API to access grammar elements (required by several other fragments) + fragment = grammarAccess.GrammarAccessFragment auto-inject {} + + // generates Java API for the generated EPackages + fragment = ecore.EMFGeneratorFragment auto-inject {} + + // the old serialization component + // fragment = parseTreeConstructor.ParseTreeConstructorFragment auto-inject {} + + // serializer 2.0 + fragment = serializer.SerializerFragment auto-inject { + generateStub = false + } + + // a custom ResourceFactory for use with EMF + fragment = resourceFactory.ResourceFactoryFragment auto-inject {} + + // The antlr parser generator fragment. + fragment = parser.antlr.XtextAntlrGeneratorFragment auto-inject { + // options = { + // backtrack = true + // } + } + + // Xtend-based API for validation + fragment = validation.ValidatorFragment auto-inject { + // composedCheck = "org.eclipse.xtext.validation.ImportUriValidator" + // composedCheck = "org.eclipse.xtext.validation.NamesAreUniqueValidator" + } + + // old scoping and exporting API + // fragment = scoping.ImportURIScopingFragment auto-inject {} + // fragment = exporting.SimpleNamesFragment auto-inject {} + + // scoping and exporting API + fragment = scoping.ImportNamespacesScopingFragment auto-inject {} + fragment = exporting.QualifiedNamesFragment auto-inject {} + fragment = builder.BuilderIntegrationFragment auto-inject {} + + // generator API + fragment = generator.GeneratorFragment auto-inject {} + + // formatter API + fragment = formatting.FormatterFragment auto-inject {} + + // labeling API + fragment = labeling.LabelProviderFragment auto-inject {} + + // outline API + fragment = outline.OutlineTreeProviderFragment auto-inject {} + fragment = outline.QuickOutlineFragment auto-inject {} + + // quickfix API + fragment = quickfix.QuickfixProviderFragment auto-inject {} + + // content assist API + fragment = contentAssist.ContentAssistFragment auto-inject {} + + // generates a more lightweight Antlr parser and lexer tailored for content assist + fragment = parser.antlr.XtextAntlrUiGeneratorFragment auto-inject {} + + // generates junit test support classes into Generator#pathTestProject + fragment = junit.Junit4Fragment auto-inject {} + + // rename refactoring + fragment = refactoring.RefactorElementNameFragment auto-inject {} + + // provides the necessary bindings for java types integration + fragment = types.TypesGeneratorFragment auto-inject {} + + // generates the required bindings only if the grammar inherits from Xbase + fragment = xbase.XbaseGeneratorFragment auto-inject {} + + // provides a preference page for template proposals + fragment = templates.CodetemplatesGeneratorFragment auto-inject {} + + // provides a compare view + fragment = compare.CompareFragment auto-inject {} + + // parse grammar and generate i18n grammar + fragment = org.eclipse.osbp.xtext.basic.generator.BasicDslGrammarI18nGenerator auto-inject {} + } + } +} + diff --git a/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/XcoreResourceFactory.java b/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/XcoreResourceFactory.java new file mode 100644 index 0000000..89ba47b --- /dev/null +++ b/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/XcoreResourceFactory.java @@ -0,0 +1,28 @@ +/** + * + * 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 + * + */ + package org.eclipse.osbp.xtext.datainterchange; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.xcore.resource.XcoreResource; + +public class XcoreResourceFactory implements Resource.Factory { + @Override + public Resource createResource(URI uri) { + XcoreResource resource = new XcoreResource(); + resource.setURI(uri); + return resource; + } + +} diff --git a/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/formatting/DataDSLFormatter.xtend b/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/formatting/DataDSLFormatter.xtend new file mode 100644 index 0000000..5a5b23a --- /dev/null +++ b/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/formatting/DataDSLFormatter.xtend @@ -0,0 +1,46 @@ +/** + * + * 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.formatting + +import com.google.inject.Inject; +import org.eclipse.xtext.formatting.impl.AbstractDeclarativeFormatter +import org.eclipse.xtext.formatting.impl.FormattingConfig +import org.eclipse.osbp.utils.xtext.GenericFormatter +import org.eclipse.xtext.xbase.services.XtypeGrammarAccess +//import org.eclipse.osbp.xtext.datainterchange.services.DataDSLGrammarAccess + +/** + * This class contains custom formatting description. + * + * see : http://www.eclipse.org/Xtext/documentation.html#formatting + * on how and when to use it + * + * Also see {@link org.eclipse.xtext.xtext.XtextFormattingTokenSerializer} as an example + */ +class DataDSLFormatter extends AbstractDeclarativeFormatter { + +// @Inject extension DataDSLGrammarAccess + @Inject XtypeGrammarAccess grammarAccess + + override protected void configureFormatting(FormattingConfig c) { + val genericFormatter = new GenericFormatter() + + genericFormatter.formatFirstLevelBlocks( c, grammar.grammar, "DataInterchange", "DataInterchangeImport" ) + genericFormatter.genericFormatting( c, grammar, grammarAccess ) + } +} diff --git a/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/jvmmodel/DataDSLJvmModelInferrer.xtend b/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/jvmmodel/DataDSLJvmModelInferrer.xtend new file mode 100644 index 0000000..724e1c9 --- /dev/null +++ b/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/jvmmodel/DataDSLJvmModelInferrer.xtend @@ -0,0 +1,1055 @@ +/** + * + * 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.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.Iterator +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.core.services.events.IEventBroker +import org.eclipse.e4.ui.model.application.MApplication +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.persistence.IPersistenceService +import org.eclipse.osbp.ui.api.metadata.IDSLMetadataService +import org.eclipse.osbp.ui.api.user.IUser +import org.eclipse.osbp.utils.constants.GeneratorConstants +import org.eclipse.osbp.utils.entitymock.IEntityImportInitializationListener +import org.eclipse.osbp.xtext.datainterchange.DataInterchange +import org.eclipse.osbp.xtext.datainterchange.DataInterchangeBean +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.common.WorkerThreadRunnable +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.milyn.Smooks +import org.milyn.SmooksFactory +import org.milyn.container.ExecutionContext +import org.osgi.framework.BundleEvent +import org.osgi.framework.BundleListener +import org.osgi.service.event.EventHandler +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. Underlying components + * are from the smooks repository + * </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) + documentation = GeneratorConstants.GENERATED_CLASSES_DOCUMENTATION + annotations += _annotationTypesBuilder.annotationRef(SuppressWarnings, "serial") + packageName = dataInterchangePackage.fullyQualifiedName.toString + it.toFields(dataInterchangePackage) + it.toConstructor(dataInterchangePackage) + it.toOperations(dataInterchangePackage) + ]) + + // create smooks classes + for (dataInterchange : dataInterchangePackage.datInts) { + var clsName2 = dataInterchange.fullyQualifiedName + acceptor.accept(dataInterchange.toClass(clsName2), + [ + superTypes += _typeReferenceBuilder.typeRef(WorkerThreadRunnable) + annotations += _annotationTypesBuilder.annotationRef(SuppressWarnings, "serial") + documentation = GeneratorConstants.GENERATED_CLASSES_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 + var name = pkg.name.toString.replace(".",":") + var String[] parts = name.split(":") + val String clsName = parts.get(parts.size-1).toFirstUpper + field = pkg.toField("log", _typeReferenceBuilder.typeRef(Logger)) [setInitializer([ append('''LoggerFactory.getLogger(«clsName»TriggerView.class)''') ])] + field.final = true + field.static = true + type.members += field + field = pkg.toField("menu", _typeReferenceBuilder.typeRef(CssLayout)) + type.members += field + field = pkg.toField("workerInfo", _typeReferenceBuilder.typeRef(EventHandler)) + type.members += field + field = pkg.toField("branding", _typeReferenceBuilder.typeRef(CssLayout)) + type.members += field + field = pkg.toField("eventBroker", _typeReferenceBuilder.typeRef(IEventBroker)) [ + annotations += _annotationTypesBuilder.annotationRef(Inject) + ] + 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("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))) + 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»''')] + ]) + // unique name + type.members += pkg.toMethod("uniqueName", _typeReferenceBuilder.typeRef(String), [ + parameters += pkg.toParameter("name", _typeReferenceBuilder.typeRef(String)) + body = [ append('''«pkg.uniqueName»''')] + ]) + // 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»''')] + ]) + // 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»''')] + ]) + // subscribe to eventBroker + type.members += pkg.toMethod("subscribe", _typeReferenceBuilder.typeRef(Void::TYPE), [ + visibility = JvmVisibility.PROTECTED + annotations += _annotationTypesBuilder.annotationRef(PostConstruct) + body = [append('''«pkg.subscribe»''')] + ]) + // unsubscribe from eventBroker + type.members += pkg.toMethod("unsubscribe", _typeReferenceBuilder.typeRef(Void::TYPE), [ + visibility = JvmVisibility.PROTECTED + annotations += _annotationTypesBuilder.annotationRef(PreDestroy) + body = [append('''«pkg.unsubscribe»''')] + ]) + // 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»''')] + ]) + } + + /** + * handle the worker progress UI. provide the appropriate code. + * + * @param pkg + * the current package inferred {@link DataInterchangePackage} + * @return code fragment + */ + def String workerInfo(DataInterchangePackage pkg) { + var body = "" + body = ''' + «body» + new EventHandler() { + @Override + public void handleEvent(Event event) { + // a worker notified this view that it is finished + String workername = (String)event.getProperty(EventUtils.DATA); + if (progressBars.containsKey(workername)) { + final WorkerThreadRunnable worker = progressBars.get(workername); + ((VerticalLayout)worker.getProgressBarArea().getParent()).removeComponent(worker.getProgressBarArea()); + progressBars.remove(workername); + } + } + }; + ''' + return body + } + + /** + * subscribe the event broker for messages on changed locale and worker progress. + * + * @param pkg + * the current package inferred {@link DataInterchangePackage} + * @return code fragment + */ + def String subscribe(DataInterchangePackage pkg) { + var body = "" + body = ''' + «body» + eventBroker.subscribe(EventBrokerMsg.WORKER_THREAD_INFO, workerInfo); + ''' + return body + } + + /** + * unsubscribe from event broker for messages. + * + * @param pkg + * the current package inferred {@link DataInterchangePackage} + * @return code fragment + */ + def String unsubscribe(DataInterchangePackage pkg) { + var body = "" + body = ''' + «body» + eventBroker.unsubscribe(workerInfo); + ''' + return body + } + + /** + * normalize package name. + * + * @param pkg + * the current package inferred {@link DataInterchangePackage} + * @return normalized package name + */ + def String toEventID(DataInterchangePackage pkg) { + return pkg.fullyQualifiedName.toString.toUpperCase.replaceAll("(\\W)","_") + } + + /** + * 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 + } + + /** + * make a name unique by concatenating a number. + * + * @param pkg + * the current package inferred {@link DataInterchangePackage} + * @return code fragment + */ + def String uniqueName(DataInterchangePackage pkg) { + var body = "" + body = ''' + «body» + Integer cnt = 0; + String searchName; + do { + if (cnt > 0) { + searchName = name+cnt.toString(); + } else { + searchName = name; + } + cnt ++; + }while(isDuplicate(searchName)); + return searchName; + ''' + 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 = ''' + buttons = new HashMap<Button, ArrayList>(); + workerInfo = «pkg.workerInfo» + 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"); + String uniqueName = uniqueName("«dataInterchange.name»"); + «dataInterchange.getBasicRunConfiguration(false, dataInterchange.getFileURL)» + «dataInterchange.defaultVariableName».setName(uniqueName); + «dataInterchange.defaultVariableName».setEventBroker(eventBroker); + «dataInterchange.defaultVariableName».setUi(UI.getCurrent()); + «dataInterchange.defaultVariableName».setDirection(WorkerThreadRunnable.Direction.IMPORT); + «IF dataInterchange.progressBarStyle!=null»«dataInterchange.defaultVariableName».setProgressBarStyleName("«dataInterchange.progressBarStyle.literal»");«ENDIF» + findButtonLayout(event.getButton()).addComponent(«dataInterchange.defaultVariableName».getProgressBarArea()); + progressBars.put(uniqueName, «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"); + String uniqueName = uniqueName("«dataInterchange.name»"); + «dataInterchange.getBasicRunConfiguration(false, dataInterchange.getFileURL)» + «dataInterchange.defaultVariableName».setName(uniqueName); + «dataInterchange.defaultVariableName».setEventBroker(eventBroker); + «dataInterchange.defaultVariableName».setUi(UI.getCurrent()); + «dataInterchange.defaultVariableName».setDirection(WorkerThreadRunnable.Direction.EXPORT); + «IF dataInterchange.progressBarStyle!=null»«dataInterchange.defaultVariableName».setProgressBarStyleName("«dataInterchange.progressBarStyle.literal»");«ENDIF» + findButtonLayout(event.getButton()).addComponent(«dataInterchange.defaultVariableName».getProgressBarArea()); + progressBars.put(uniqueName, «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%"); + user.addUserLocaleListener(this); + ''' + return body + } + + def String getDefaultVariableName(DataInterchange dataInterchange) { + return dataInterchange.name.toFirstLower + } + + def String getBasicRunConfiguration(DataInterchange dataInterchange, boolean fqClass, String fileURL) { + var className = "" + if (fqClass) { + className = dataInterchange.fullyQualifiedName.toString + } + else { + className = dataInterchange.name + } + return ''' + «className» «dataInterchange.getDefaultVariableName» = new «className»(); + «dataInterchange.getDefaultVariableName».setFileURL("«fileURL»"); + «dataInterchange.getDefaultVariableName».setPersistenceService(persistenceService); + ''' + } + + 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 smooks 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("smooksOSGIFactory", _typeReferenceBuilder.typeRef(SmooksFactory)) [setInitializer([ append('''null''') ])] + type.members += field + field = dataInterchange.toField("smooks", _typeReferenceBuilder.typeRef(Smooks)) + type.members += field +// field = dataInterchange.toField("xmlBinding", _typeReferenceBuilder.typeRef(XMLBinding)) +// 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("executionContext", _typeReferenceBuilder.typeRef(ExecutionContext)) + 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("pollingInterval", _typeReferenceBuilder.typeRef(int)) [setInitializer([ append('''500''') ])] + 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.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.performSmooks»''')] + ]) + 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.isMacOS()) { + path = filePath.substring("file://".length()); + } + try { + fileURL = new URL(path); + } catch (MalformedURLException e1) { + if(e1.getMessage().startsWith("unknown protocol")) { + try { + fileURL = Paths.get(path).toUri().toURL(); + } catch (MalformedURLException e2) { + log.error(e2.getLocalizedMessage()+e2.getCause()); + } + } + } + ''' + + /** + * init smooks 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 = + ''' + if(getEventBroker()!=null) { + pollingInterval = UI.getCurrent().getPollInterval(); + UI.getCurrent().setPollInterval(500); + } + 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 smooks + setProgressBarEnabled(true); + setProgressIndeterminated(true); + if (log.isDebugEnabled()) log.debug("initializing smooks factory"); + smooksOSGIFactory = new SmooksOSGIFactory(FrameworkUtil.getBundle(this.getClass())); + smooks = smooksOSGIFactory.createInstance(FrameworkUtil.getBundle(this.getClass()).getResource("«DSLOutputConfigurationProvider.SMOOKS_OUTPUT_DIRECTORY»/«dataInterchange.name»-"+direction.toString().toLowerCase()+".xml").openStream()); + // prepare execution context + executionContext = smooks.createExecutionContext(); + executionContext.setEventListener(this); + // get entity manager + if (log.isDebugEnabled()) log.debug("opening entity manager to persist smooks results"); + getPersistenceService().registerPersistenceUnit("«firstEntity.entity.persistenceUnit»", «firstEntity.entity.fullyQualifiedName».class); + em = getPersistenceService().getEntityManagerFactory("«firstEntity.entity.persistenceUnit»").createEntityManager(); + «IF dataInterchange.createReport» + // create a filtering report -- impacts performance + if (log.isDebugEnabled()) log.debug("reporting is on - impacting performance"); + String location = FrameworkUtil.getBundle(this.getClass()).getLocation()+"«DSLOutputConfigurationProvider.SMOOKS_OUTPUT_DIRECTORY»/«dataInterchange.name»-"+direction.toString().toLowerCase()+"-report.html"; + executionContext.setEventListener(new HtmlReportGenerator(location)); + «ENDIF» + } catch (Exception e) { + if(getEventBroker()!=null) { + UI.getCurrent().setPollInterval(pollingInterval); + } + log.error(e.getLocalizedMessage()+e.getCause()); + return false; + } + if(direction == Direction.EXPORT) { + int openTry = 0; + file = null; + URI uri = null; + try { + uri = fileURL.toURI(); + } catch (URISyntaxException e) { + log.error(e.getLocalizedMessage()+e.getCause()); + 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) { + log.error(e.getLocalizedMessage()+e.getCause()); + return false; + } + } catch (IOException e) { + log.error(e.getLocalizedMessage()+e.getCause()); + return false; + } + }while(file == null); + out = new BufferedOutputStream(file); + } + return true; + ''' + return body + } + + /** + * use smooks 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 performSmooks(DataInterchange dataInterchange) { + var firstEntity = (dataInterchange.path.iterator.next as DataInterchangeBean) + var body = ''' + if(!init(getDirection())) { + 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); + } + // execute the smooks filtering + JavaResult result = new JavaResult(); + InputStream in = fileURL.openStream(); + byte[] contents = StreamUtils.readStream(in); + setLength(contents.length); + setAvgElementSize(«IF dataInterchange.elementSize==0»10«ELSE»«dataInterchange.elementSize»«ENDIF»); + StreamSource source = new StreamSource(new ByteArrayInputStream(contents)); + ''' + for (path:dataInterchange.path) { + for (lookup:path.lookup) { + if (lookup.cached) { + body = ''' + «body» + em.setProperty(PersistenceUnitProperties.CACHE_SIZE_+"«lookup.entity.fullyQualifiedName»", "«lookup.cacheSize»"); + ''' + } + } + } + body = ''' + «body» + PersistenceUtil.setDAORegister(executionContext, new EntityManagerRegister(em)); + // execute smooks filtering + if (log.isDebugEnabled()) log.debug("filtering starts"); + setProgressIndeterminated(false); + if (importListener != null) { + importListener.notifyInitializationStep("datainterchange Warehouses load..", 0.4, 0.47, 0, 0); + } + smooks.filterSource(executionContext, source, result); + if (importListener != null) { + importListener.notifyInitializationStep("datainterchange Warehouses load...", 0.4, 0.48, 0, 0); + } + if (log.isDebugEnabled()) log.debug("smooks filtering finished"); + ''' + if (firstEntity.recordList) { + body = ''' + «body» + // retrieve bean list + List<«firstEntity.entity.fullyQualifiedName»> «firstEntity.entity.name.toFirstLower»List = Arrays.asList((«firstEntity.entity.fullyQualifiedName»[]) result.getBean("«firstEntity.entity.name»List")); + // persist + em.getTransaction().begin(); + if (log.isDebugEnabled()) log.debug("persisting results"); + int total = «firstEntity.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(«firstEntity.entity.fullyQualifiedName» «firstEntity.entity.name.toFirstLower»:«firstEntity.entity.name.toFirstLower»List) { + try { + em.persist(«firstEntity.entity.name.toFirstLower»); + } + catch (ConstraintViolationException cve) { + log.error("«firstEntity.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» + // retrieve the root bean + «firstEntity.entity.fullyQualifiedName» «firstEntity.entity.name.toFirstLower» = («firstEntity.entity.fullyQualifiedName») result.getBean("«firstEntity.entity.name»"); + // persist + em.getTransaction().begin(); + if (log.isDebugEnabled()) log.debug("persisting results"); + em.persist(«firstEntity.entity.name.toFirstLower»); + if (log.isDebugEnabled()) log.debug("committing results"); + em.getTransaction().commit(); + ''' + } + if (firstEntity.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 «firstEntity.entity.name» set «firstEntity.latestProperty.name» = 0").executeUpdate(); + em.createQuery("update «firstEntity.entity.name» set «firstEntity.latestProperty.name» = 1 where «»id= :id").setParameter("id", «firstEntity.entity.name.toFirstLower».getId()).executeUpdate(); + if (log.isDebugEnabled()) log.debug("committing mark"); + em.getTransaction().commit(); + ''' + } + if (dataInterchange.refreshEnabled) { + body = ''' + «body» + if(getEventBroker()!=null) { + getEventBroker().send(EventBrokerMsg.REFRESH_VIEW+"«dataInterchange.refresh»", "*"); + } + ''' + } + body = ''' + «body» + if (log.isDebugEnabled()) log.debug("results persisted"); + ''' + var iter = dataInterchange.path.iterator + var root = (iter.next as DataInterchangeBean).entity + body = ''' + «body» + } else { + if (log.isDebugEnabled()) log.debug("prepare export"); +««« «IF dataInterchange.fileEndpoint instanceof DataInterchangeFileXML» +««« // Create and initilise the XMLBinding instance... +««« xmlBinding = new XMLBinding(smooks); +««« xmlBinding.intiailize(); +««« xmlBinding.setOmitXMLDeclaration(true); +««« «ENDIF» +««« «dataInterchange.buildEntityGraph(iter, root)» + int pageNumber = 1; + int pageSize = 1000; + 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(«firstEntity.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<«firstEntity.entity.fullyQualifiedName»> criteriaQuery = criteriaBuilder.createQuery(«firstEntity.entity.fullyQualifiedName».class); + Root<«firstEntity.entity.fullyQualifiedName»> from = criteriaQuery.from(«firstEntity.entity.fullyQualifiedName».class); + /* ... not necessary due to eager loading of entities via JPA ... «dataInterchange.buildJoins(iter, root)» ...*/ + CriteriaQuery<«firstEntity.entity.fullyQualifiedName»> select = criteriaQuery.multiselect(from); + + TypedQuery<«firstEntity.entity.fullyQualifiedName»> typedQuery = em.createQuery(select); +««« typedQuery.setHint(QueryHints.JPA_LOAD_GRAPH, «firstEntity.entity.name.toFirstLower»Graph); + setProgressIndeterminated(false); + while (pageNumber < count.intValue()) { + if (log.isDebugEnabled()) log.debug("fetch and process entry "+pageNumber+" to "+(pageNumber+pageSize)); + typedQuery.setFirstResult(pageNumber - 1); + typedQuery.setMaxResults(pageSize); + List<«firstEntity.entity.fullyQualifiedName»> queryResults = typedQuery.getResultList(); +««« «IF dataInterchange.fileEndpoint instanceof DataInterchangeFileCSV» + StringWriter writer = new StringWriter(); + smooks.filterSource(executionContext, new JavaSource(queryResults), new StreamResult(writer)); + out.write(writer.toString().getBytes()); +««« «ELSEIF dataInterchange.fileEndpoint instanceof DataInterchangeFileXML» +««« for(«firstEntity.entity.fullyQualifiedName» row:queryResults) { +««« String outXML = xmlBinding.toXML(row); +««« out.write(outXML.getBytes()); +««« } +««« JAXBContext jc = JAXBContext.newInstance(«firstEntity.entity.fullyQualifiedName».class); +««« Marshaller marshaller = jc.createMarshaller(); +««« marshaller.marshal(queryResults, out); +««« «ENDIF» + pageNumber += pageSize; + } + if (log.isDebugEnabled()) log.debug("export finished"); + } + ''' + body = ''' + «body» + } catch (Exception e) { + log.error("«dataInterchange.name»: "+e.getLocalizedMessage()+e.getCause(), e); + } finally { + if(file != null) { + try { + out.close(); + file.close(); + } catch (IOException e) { + log.error(e.getLocalizedMessage()+e.getCause()); + } + } + smooks.close(); + if(getEventBroker()!=null) { + UI.getCurrent().setPollInterval(pollingInterval); + } + // close everything + if (em != null) { + em.close(); + } + if (log.isDebugEnabled()) log.debug("datainterchange finished"); + } + ''' + return body + } + + /** + * This seems to be not necessary, because JPA seems to load the entities eager itself! + * With this functionality active, the sql result set would contain all root entities multiple times! + */ + @Deprecated + def buildJoins(DataInterchange interchange, Iterator<DataInterchangeBean> iter, LEntity rootEntity) { + var root = rootEntity + var body = "" + if(iter.hasNext) { + body = '''«body»from''' + } + while(iter.hasNext) { + var entity = (iter.next as DataInterchangeBean).entity + for(f:root.features) { + if (f instanceof LReference && f.toMany && f.type instanceof LEntity && f.type.toName.equals(entity.toName)) { + // one to many for the entity in sequence is found + body = '''«body».fetch("«f.name»", JoinType.LEFT)''' + } + } + root = entity + } + if(!body.empty) { + body = body + ";" + } + 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))); + } + }''' +} diff --git a/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/jvmmodel/DataDSLModelGenerator.xtend b/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/jvmmodel/DataDSLModelGenerator.xtend new file mode 100644 index 0000000..b67aa60 --- /dev/null +++ b/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/jvmmodel/DataDSLModelGenerator.xtend @@ -0,0 +1,1060 @@ +/** + * + * 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("<","<").replace(">",">").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) + } +} diff --git a/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/scoping/DataDSLScopeProvider.xtend b/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/scoping/DataDSLScopeProvider.xtend new file mode 100644 index 0000000..796c5fb --- /dev/null +++ b/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/scoping/DataDSLScopeProvider.xtend @@ -0,0 +1,233 @@ +/** + * + * 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.scoping + +import org.eclipse.osbp.xtext.datainterchange.DataDSLPackage +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.DataInterchangeLookup +import org.eclipse.osbp.xtext.datainterchange.DataInterchangeMarkerEntity +import javax.inject.Inject +import org.eclipse.emf.ecore.EObject +import org.eclipse.emf.ecore.EReference +import org.eclipse.xtext.resource.EObjectDescription +import org.eclipse.xtext.resource.IEObjectDescription +import org.eclipse.xtext.scoping.IScope +import org.eclipse.xtext.scoping.impl.MapBasedScope +import org.eclipse.xtext.xbase.annotations.typesystem.XbaseWithAnnotationsBatchScopeProvider +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.LReference +import org.eclipse.osbp.dsl.semantic.entity.LEntity +import org.eclipse.osbp.dsl.semantic.entity.LEntityReference + +class DataDSLScopeProvider extends XbaseWithAnnotationsBatchScopeProvider { + @Inject extension ModelExtensions + @Inject extension EntityTypesBuilder + + override getScope(EObject context, EReference reference) { + if (reference == DataDSLPackage.Literals.DATA_INTERCHANGE_BEAN__LATEST_PROPERTY) { + return getScope_Data_Entity_latest(context, reference) + } else if (reference == DataDSLPackage.Literals.DATA_INTERCHANGE_EXPRESSION__TARGET_PROPERTY) { + return getScope_Data_Target_property(context, reference, true) + } else if (reference == DataDSLPackage.Literals.DATA_INTERCHANGE_FORMAT__TARGET_PROPERTY) { + return getScope_Data_Target_property(context, reference, true) + } else if (reference == DataDSLPackage.Literals.DATA_INTERCHANGE_ENTITY_EXPRESSION__ENTITY) { + return getScope_Data_Expression_entity(context, reference, true) + } else if (reference == DataDSLPackage.Literals.DATA_INTERCHANGE_ENTITY_EXPRESSION__PROPERTY) { + return getScope_Data_Expression_entity(context, reference, false) + } else if (reference == DataDSLPackage.Literals.DATA_INTERCHANGE_LOOKUP__TARGET_PROPERTY) { + return getScope_Data_Target_property(context, reference, false) + } else if (reference == DataDSLPackage.Literals.DATA_INTERCHANGE_LOOKUP__QUERY_PROPERTY) { + return getScope_Data_Lookup_queryProperty(context, reference) + } else if (reference == DataDSLPackage.Literals.DATA_INTERCHANGE_LOOKUP__ENTITY) { + return getScope_Data_Lookup_lookupEntity(context, reference) + } else if (reference == DataDSLPackage.Literals.DATA_INTERCHANGE_BEAN__ENTITY) { + return getScope_Data_Bean_Entity(context, reference) + } else if (reference == DataDSLPackage.Literals.DATA_INTERCHANGE_MAPPING__PROPERTY) { + return getScope_Data_Target_property(context, reference, true) + } else if (reference == DataDSLPackage.Literals.DATA_INTERCHANGE_MARKER_ENTITY__MARKER_ENTITY) { + return getScope_Data_Markerpath_entity(context, reference) + } else if (reference == DataDSLPackage.Literals.DATA_INTERCHANGE_MARKER_ENTITY__MARKER_PROPERTY) { + return getScope_Data_Entity_latest(context, reference) + } else { + super.getScope(context, reference) + } + } + + def getScope_Data_Bean_Entity(EObject context, EReference reference) { + var result = <IEObjectDescription>newArrayList + var eObj = context.eContainer + while (!(eObj instanceof DataInterchange)) { + eObj = eObj.eContainer + } + if (eObj != null) { + var DataInterchangeBean previousEntity = null + for(diEntity:(eObj as DataInterchange).path) { + // find me + if (previousEntity != null) { + // remove this entity from result, we already used it + var IEObjectDescription delObj = null + for(r:result) { + if (r.name.toString.equals(previousEntity.entity.name)) { + delObj = r + } + } + if(delObj != null) { + result.remove(delObj) + } + // scoping refers to the previous owner + for(f:previousEntity.entity.features) { + if (f instanceof LReference) { + if (f.cascading && f.toMany) { + var ref = (f as LEntityReference) + result.add(EObjectDescription.create(ref.type.toName, ref.type)) + } + } + } + } + if (!diEntity.equals(context)) { + previousEntity = diEntity + } + else if (previousEntity == null) { + return super.getScope(context, reference) + } + } + } + return MapBasedScope.createScope(IScope.NULLSCOPE, result) + } + + def getScope_Data_Lookup_queryProperty(EObject context, EReference reference) { + var result = <IEObjectDescription>newArrayList + if (context != null && context instanceof DataInterchangeLookup) { + var entity = (context as DataInterchangeLookup).entity + for (prop : entity.features) { + if (prop instanceof LAttribute && !prop.toMany) { + result.add(EObjectDescription.create((prop as LAttribute).name, (prop as LAttribute))) + } + } + } + return MapBasedScope.createScope(IScope.NULLSCOPE, result) + } + + def getScope_Data_Lookup_lookupEntity(EObject context, EReference reference) { + var result = <IEObjectDescription>newArrayList + var targetProperty = (context as DataInterchangeLookup).targetProperty + var eObj = context.eContainer + while (!(eObj instanceof DataInterchangeBean)) { + eObj = eObj.eContainer + } + if (eObj != null) { + var entity = (eObj as DataInterchangeBean).entity + for (prop : entity.features) { + if (prop instanceof LReference && !prop.toMany && (prop as LReference).name.equals(targetProperty.toName)) { + result.add(EObjectDescription.create((prop as LReference).type.name, (prop as LReference).type)) + } + } + } + return MapBasedScope.createScope(IScope.NULLSCOPE, result) + } + + def getScope_Data_Expression_entity(EObject context, EReference reference, boolean filterEntity) { + var result = <IEObjectDescription>newArrayList + var targetProperty = (context as DataInterchangeEntityExpression).targetProperty + var fromEntity = (context as DataInterchangeEntityExpression).entity + var eObj = context.eContainer + while (!(eObj instanceof DataInterchange)) { + eObj = eObj.eContainer + } + if (eObj != null) { + for (path : (eObj as DataInterchange).path) { + for (f:path.entity.features) { + if (f instanceof LAttribute && (f as LAttribute).type.name.equals(targetProperty.type.name)) { + if (filterEntity) { + result.add(EObjectDescription.create(path.entity.toName, path.entity)) + } else if (fromEntity == null || path.entity.toName.equals(fromEntity.toName)) { + result.add(EObjectDescription.create((f as LAttribute).toName, (f as LAttribute))) + } + } + } + } + } + return MapBasedScope.createScope(IScope.NULLSCOPE, result) + } + + def getScope_Data_Target_property(EObject context, EReference reference, boolean filterAttributes) { + var result = <IEObjectDescription>newArrayList + var eObj = context.eContainer + while (!(eObj instanceof DataInterchangeBean)) { + eObj = eObj.eContainer + } + if (eObj != null) { + var entity = (eObj as DataInterchangeBean).entity + var marker = (eObj as DataInterchangeBean).latestProperty + for (prop : entity.features) { + if (filterAttributes) { + if (prop instanceof LAttribute && (marker==null || !prop.toName.equals(marker.toName))) { + result.add(EObjectDescription.create((prop as LAttribute).name, (prop as LAttribute))) + } + } else { + if (prop instanceof LReference && !prop.toMany) { + result.add(EObjectDescription.create((prop as LReference).name, (prop as LReference))) + } + } + } + } + return MapBasedScope.createScope(IScope.NULLSCOPE, result) + } + + def getScope_Data_Entity_latest(EObject context, EReference reference) { + var result = <IEObjectDescription>newArrayList + var LEntity rootEntity = null + if (context != null) { + switch context { + DataInterchangeBean: { + rootEntity = (context as DataInterchangeBean).entity + } + DataInterchangeMarkerEntity: { + rootEntity = (context as DataInterchangeMarkerEntity).markerEntity + } + } + for (prop : rootEntity.features) { + if (prop instanceof LAttribute && "boolean".equals((prop as LAttribute).type.name)) { + result.add(EObjectDescription.create((prop as LAttribute).name, (prop as LAttribute))) + } + } + } + return MapBasedScope.createScope(IScope.NULLSCOPE, result) + } + + def getScope_Data_Markerpath_entity(EObject context, EReference reference) { + var result = <IEObjectDescription>newArrayList + var eObj = context.eContainer + while (!(eObj instanceof DataInterchangeLookup)) { + eObj = eObj.eContainer + } + if (eObj != null) { + var entity = (eObj as DataInterchangeLookup).entity + for (f:entity.references) { + if (!f.toMany) { + result.add(EObjectDescription.create(f.type.toName , f.type)) + } + } + } + return MapBasedScope.createScope(IScope.NULLSCOPE, result) + } +} diff --git a/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/validation/DataDSLValidator.xtend b/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/validation/DataDSLValidator.xtend new file mode 100644 index 0000000..c447636 --- /dev/null +++ b/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/validation/DataDSLValidator.xtend @@ -0,0 +1,38 @@ +/** + * + * 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.validation +//import org.eclipse.xtext.validation.Check + +/** + * Custom validation rules. + * + * see http://www.eclipse.org/Xtext/documentation.html#validation + */ +class DataDSLValidator extends AbstractDataDSLValidator { + +// public static val INVALID_NAME = 'invalidName' +// +// @Check +// def checkGreetingStartsWithCapital(Greeting greeting) { +// if (!Character.isUpperCase(greeting.name.charAt(0))) { +// warning('Name should start with a capital', +// MyDslPackage.Literals.GREETING__NAME, +// INVALID_NAME) +// } +// } +} diff --git a/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/valueconverter/DataDSLQualifiedNameProvider.java b/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/valueconverter/DataDSLQualifiedNameProvider.java new file mode 100644 index 0000000..a38751d --- /dev/null +++ b/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/valueconverter/DataDSLQualifiedNameProvider.java @@ -0,0 +1,36 @@ +/** + * + * 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 + * + */ + package org.eclipse.osbp.xtext.datainterchange.valueconverter; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.xtext.naming.IQualifiedNameConverter; +import org.eclipse.xtext.naming.QualifiedName; +import org.eclipse.xtext.xbase.scoping.XbaseQualifiedNameProvider; + +import com.google.inject.Inject; + +@SuppressWarnings("restriction") +public class DataDSLQualifiedNameProvider extends XbaseQualifiedNameProvider { + + @Inject + private IQualifiedNameConverter qualifiedNameConverter; + + @Override + public QualifiedName getFullyQualifiedName(EObject obj) { + if (obj == null) { + return QualifiedName.create(""); + } + return super.getFullyQualifiedName(obj); + } +} diff --git a/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/valueconverter/DataDSLValueConverterService.java b/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/valueconverter/DataDSLValueConverterService.java new file mode 100644 index 0000000..4020c30 --- /dev/null +++ b/org.eclipse.osbp.xtext.datainterchange/src/org/eclipse/osbp/xtext/datainterchange/valueconverter/DataDSLValueConverterService.java @@ -0,0 +1,41 @@ +/** + * 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 - Initial implementation + */ +package org.eclipse.osbp.xtext.datainterchange.valueconverter; + +import org.eclipse.osbp.xtext.basic.valueconverter.TRANSLATABLESTRINGValueConverter; +import org.eclipse.xtext.conversion.IValueConverter; +import org.eclipse.xtext.conversion.ValueConverter; +import org.eclipse.xtext.xbase.conversion.XbaseValueConverterService; + +import com.google.inject.Inject; +import com.google.inject.Singleton; + +/** + * Adds a value conversion for the QualifiedNameWithWildCard rule. + * + */ +@SuppressWarnings("restriction") +@Singleton +public class DataDSLValueConverterService extends XbaseValueConverterService { + @Inject + private TRANSLATABLESTRINGValueConverter converter; + + @ValueConverter(rule = "QualifiedNameWithWildCard") + public IValueConverter<String> getQualifiedNameWithWildCard() { + return getQualifiedNameValueConverter(); + } + + @ValueConverter(rule = "TRANSLATABLESTRING") + public IValueConverter<String> getTranslatableStringValueConverter() { + return converter; + } + +} |