diff --git a/org.eclipse.lyo.oslc4j.codegenerator/META-INF/MANIFEST.MF b/org.eclipse.lyo.oslc4j.codegenerator/META-INF/MANIFEST.MF
index ec134454..9d963345 100644
--- a/org.eclipse.lyo.oslc4j.codegenerator/META-INF/MANIFEST.MF
+++ b/org.eclipse.lyo.oslc4j.codegenerator/META-INF/MANIFEST.MF
@@ -24,7 +24,12 @@ Export-Package: org.eclipse.lyo.oslc4j.codegenerator.files,
org.eclipse.lyo.oslc4j.codegenerator.jsp,
org.eclipse.lyo.oslc4j.codegenerator.staticFiles,
org.eclipse.lyo.oslc4j.codegenerator.main,
- org.eclipse.lyo.oslc4j.codegenerator.services
+ org.eclipse.lyo.oslc4j.codegenerator.services,
+ org.eclipse.lyo.oslc4j.codegenerator.python.files,
+ org.eclipse.lyo.oslc4j.codegenerator.python.config,
+ org.eclipse.lyo.oslc4j.codegenerator.python.staticFiles,
+ org.eclipse.lyo.oslc4j.codegenerator.python.main,
+ org.eclipse.lyo.oslc4j.codegenerator.python.services
Bundle-ClassPath: bin/,
.
diff --git a/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/config/generateConfigFiles.mtl b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/config/generateConfigFiles.mtl
new file mode 100644
index 00000000..7382b300
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/config/generateConfigFiles.mtl
@@ -0,0 +1,25 @@
+[comment encoding = UTF-8 /]
+[comment
+/*
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License 1.0
+ * which is available at http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Simple
+ */
+/]
+[module generateConfigFiles('http://org.eclipse.lyo/oslc4j/adaptorInterface', 'http://org.eclipse.lyo/oslc4j/vocabulary', 'http://www.eclipse.org/emf/2002/Ecore')/]
+
+
+[template public generateConfigFiles(aSpecification : Specification)]
+[file ('requirements.txt', false, 'UTF-8')]
+oslc4py-client
+rdflib
+[/file]
+[/template]
diff --git a/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/files/generateAdaptorPackageInfo.mtl b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/files/generateAdaptorPackageInfo.mtl
new file mode 100644
index 00000000..3c823ebf
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/files/generateAdaptorPackageInfo.mtl
@@ -0,0 +1,40 @@
+[comment encoding = UTF-8 /]
+[comment
+/*
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License 1.0
+ * which is available at http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Simple
+ */
+/]
+[module generateAdaptorPackageInfo('http://org.eclipse.lyo/oslc4j/adaptorInterface', 'http://org.eclipse.lyo/oslc4j/vocabulary')/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::services::resourceServices/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::services::services/]
+
+[template public generateAdaptorPackageInfo(resources : Set(Resource), defaultFilesPath : String, defaultPackageName : String)]
+[let generatedResources : Set(Resource) = resources->select(r : Resource | r.generate())]
+[if (resources->size() > 0)]
+ [comment This can be any resource because it's only used for constructing correct path /]
+ [let aResource : Resource = resources->any(true)]
+ [file (aResource.pythonClassFullFolderName(null, defaultFilesPath, defaultPackageName).concatenatePaths('__init__.py'), false, 'UTF-8')]
+ [for (r : Resource | generatedResources->sortedBy(name))]
+from .[r.pythonClassName()/] import [r.pythonClassName()/]
+ [/for]
+# [protected ('imports')]
+# [/protected]
+ [/file]
+ [/let]
+[/if]
+[/let]
+[/template]
+
+[template public generateAdaptorPackageInfo(resourcesOnSameFolderPath: Set(Resource), contextAdaptorInterface : AdaptorInterface, defaultFilesPath : String, defaultPackageName : String)]
+[generateAdaptorPackageInfo(resourcesOnSameFolderPath, contextAdaptorInterface.filesBasePath(defaultFilesPath), contextAdaptorInterface.pythonBasePackageName(defaultPackageName))/]
+[/template]
diff --git a/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/files/generateDomainSpecificationConstants.mtl b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/files/generateDomainSpecificationConstants.mtl
new file mode 100644
index 00000000..9a759ea6
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/files/generateDomainSpecificationConstants.mtl
@@ -0,0 +1,52 @@
+[comment encoding = UTF-8 /]
+[comment
+/*
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License 1.0
+ * which is available at http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Simple
+ */
+/]
+[module generateDomainSpecificationConstants('http://org.eclipse.lyo/oslc4j/adaptorInterface', 'http://org.eclipse.lyo/oslc4j/vocabulary')/]
+
+[import org::eclipse::lyo::oslc4j::codegenerator::python::services::fileServices/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::services::services/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::services::adaptorInterfaceServices/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::services::domainSpecificationServices/]
+
+[template public generateDomainSpecificationConstants(aDomainSpecification : DomainSpecification, defaultFilesPath : String, defaultPackageName : String)]
+[let rootInitFileName : String = aDomainSpecification.pythonFilesBasePath(null, defaultFilesPath).concatenatePaths('__init__.py')]
+[file (rootInitFileName, false, 'UTF-8')]
+# [protected ('imports')]
+# [/protected]
+[/file]
+[/let]
+[let packageInitFileName : String = aDomainSpecification.pythonFullFolderNameForConstants(null, defaultFilesPath, defaultPackageName).concatenatePaths('__init__.py')]
+[file (packageInitFileName, false, 'UTF-8')]
+# [protected ('imports')]
+# [/protected]
+[/file]
+[/let]
+[file (aDomainSpecification.pythonFullFileNameForConstants(null, defaultFilesPath, defaultPackageName), false, 'UTF-8')]
+import rdflib
+
+# [protected ('imports')]
+# [/protected]
+
+[aDomainSpecification.domainSpecificationImplicitVocabularyNamespaceConstantName()/] = rdflib.Namespace("[aDomainSpecification.namespaceURI/]")
+
+# [protected ('constants')]
+# [/protected]
+[/file]
+[/template]
+
+[template public generateDomainSpecificationConstants(aDomainSpecification : DomainSpecification, anAdaptorInterface : AdaptorInterface, defaultFilesPath : String, defaultPackageName : String)]
+[aDomainSpecification.generateDomainSpecificationConstants(aDomainSpecification.filesBasePath(anAdaptorInterface, defaultFilesPath), aDomainSpecification.pythonPackageNameForConstants(anAdaptorInterface, defaultPackageName))/]
+[/template]
diff --git a/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/files/generateResource.mtl b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/files/generateResource.mtl
new file mode 100644
index 00000000..c8938997
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/files/generateResource.mtl
@@ -0,0 +1,214 @@
+[comment encoding = UTF-8 /]
+[comment
+/*
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License 1.0
+ * which is available at http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Simple
+ */
+/]
+[module generateResource('http://org.eclipse.lyo/oslc4j/adaptorInterface', 'http://org.eclipse.lyo/oslc4j/vocabulary')/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::services::vocabularyServices/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::services::adaptorInterfaceServices/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::services::domainSpecificationServices/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::services::resourceServices/]
+
+[import org::eclipse::lyo::oslc4j::codegenerator::python::services::resourcePropertyServices/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::services::services/]
+
+[template public generateClassHeader(aResource : Resource, contextAdaptorInterface : AdaptorInterface)]
+# [protected ('Copyright')]
+#
+# Copyright (c) 2020 Contributors to the Eclipse Foundation
+#
+# See the NOTICE file(s) distributed with this work for additional
+# information regarding copyright ownership.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Distribution License 1.0 which is available at
+# http://www.eclipse.org/org/documents/edl-v10.php.
+#
+# SPDX-License-Identifier: BSD-3-Simple
+#
+# This file is generated by Lyo Designer (https://www.eclipse.org/lyo/)
+#
+# [/protected]
+[/template]
+
+[template public generateImports(aResource : Resource, contextAdaptorInterface : AdaptorInterface, defaultPackageName : String)]
+[if (hasDateTimeProperty(aResource))]from datetime import datetime[/if]
+[if (hasSetProperty(aResource))]from typing import Set[/if]
+from oslc4py_client.annotation_types.Occurs import Occurs
+from oslc4py_client.annotation_types.ValueType import ValueType
+from oslc4py_client.annotation_types.Representation import Representation
+from oslc4py_client.OSLCResource import OSLCResource
+[if (hasLinkProperty(aResource))]from oslc4py_client.Link import Link[/if]
+from oslc4py_client.decorators import oslc_description, oslc_name, oslc_namespace, oslc_rdf_collection_type, oslc_occurs, oslc_property_definition, oslc_resource_shape, oslc_value_type, oslc_representation, oslc_range, oslc_read_only, oslc_title, oslc_member_property, oslc_allowed_values
+
+from [aResource.definingDomainSpecification().pythonPackageNameForConstants(contextAdaptorInterface, defaultPackageName)/].[aResource.definingDomainSpecification().pythonNameForConstants()/] import [aResource.definingDomainSpecification().domainSpecificationImplicitVocabularyNamespaceConstantName()/]
+[if (not aResource.directParentResource().oclIsUndefined() and aResource.directParentResource() <> aResource)]from [aResource.directParentResource().pythonClassPackageName(contextAdaptorInterface, defaultPackageName)/].[aResource.directParentResource().pythonClassName()/] import [aResource.directParentResource().pythonClassName()/][/if]
+[for (aDomainSpecification: DomainSpecification | (aResource.resourceProperties->union(aResource.interfaceProperties()->asSet())->collect(p: ResourceProperty | Set{p.definingDomainSpecification()}->union(p.range.definingDomainSpecification()->asSet())))->flatten()->asSet()->sortedBy(name))]from [aDomainSpecification.pythonPackageNameForConstants(contextAdaptorInterface, defaultPackageName)/].[aDomainSpecification.pythonNameForConstants()/] import [aDomainSpecification.domainSpecificationImplicitVocabularyNamespaceConstantName()/]
+[/for]
+[for (aVocabulary: Vocabulary | ((aResource.resourceProperties->asSequence())->union(interfaceProperties(aResource)))->asSet()
+ ->select(p: ResourceProperty | not (p.propertyDefinition.oclIsUndefined()))
+ ->collect(p: ResourceProperty | p.propertyDefinition.definingVocabulary())
+ ->flatten()->asSet()->sortedBy(label))]from [aVocabulary.pythonPackageNameForConstants(contextAdaptorInterface, defaultPackageName)/].[aVocabulary.pythonNameForConstants()/] import [aVocabulary.vocabularyNamespaceConstantName()/]
+[/for]
+[for (r: Resource | ((aResource.resourceProperties->asSequence())->union(interfaceProperties(aResource)))
+ ->select(p: ResourceProperty |
+ (p.valueType.toString() = 'LocalResource' and p.range->size() = 1) or
+ (p.valueType.toString() = 'Resource' and not p.representation.oclIsUndefined() and p.representation.toString().equalsIgnoreCase('inline') and p.range->size() = 1)
+ )
+ ->collect(p: ResourceProperty | p.range)->flatten()->asSet()
+ ->sortedBy(name))]
+[if (r <> aResource)]
+from [r.pythonClassPackageName(contextAdaptorInterface, defaultPackageName)/].[r.pythonClassName()/] import [r.pythonClassName()/]
+[/if]
+[/for]
+# [protected ('imports')]
+# [/protected]
+[/template]
+
+[template public generatePreClassCode(aResource : Resource, contextAdaptorInterface : AdaptorInterface)]
+# [protected ('preClassCode')]
+# [/protected]
+[/template]
+
+[template public generateClassAnnotations(aResource : Resource)]
+# [protected ('classAnnotations')]
+# [/protected]
+[pythonNamespaceAnnotation(aResource)/]
+[pythonNameAnnotation(aResource)/]
+[pythonResourceShapeAnnotation(aResource)/]
+[/template]
+
+[template public generateClassDeclaration(aResource : Resource)]
+class [aResource.pythonClassName()/]([if (aResource.directParentResource().oclIsUndefined())]OSLCResource[else][pythonClassName(aResource.directParentResource())/][/if]):
+[/template]
+
+[template public generateInstanceAttributes(aResource : Resource)]
+[for (aProperty: ResourceProperty | ((aResource.resourceProperties->asSequence())->union(interfaceProperties(aResource))))]
+# [protected ('attributeAnnotation:'.concat(pythonAttributeName(aProperty, aResource)))]
+# [/protected]
+self._[aProperty.pythonAttributeName(aResource)/] = [aProperty.pythonAttributeInitialConstruction()/]
+[/for]
+[/template]
+
+[template public generateClassAttributes(aResource : Resource)]
+# [protected ('classAttributes')]
+# [/protected]
+[/template]
+
+[template public generateClassMethods(aResource : Resource)]
+# [protected ('classMethods')]
+# [/protected]
+[/template]
+
+[template public generateConstructor(aResource : Resource)]
+def __init__(self, **kwargs):
+ super().__init__(**kwargs)
+ # [protected ('constructor')]
+ # [/protected]
+ [generateInstanceAttributes(aResource)/]
+[/template]
+
+[template public generateAddToAttributeMethods(aResource : Resource)]
+[for (aProperty: ResourceProperty | ((aResource.resourceProperties->asSequence())->union(interfaceProperties(aResource))))]
+ [if (Sequence{'zeroOrMany', 'oneOrMany'}->includes(aProperty.occurs.toString()))]
+def add_[pythonAttributeName(aProperty, aResource)/](self, value: [pythonAttributeBaseType(aProperty) /]):
+ self.[pythonAttributeName(aProperty, aResource) /].add(value)
+
+ [/if]
+[/for]
+[/template]
+
+[template public generateGetter(aProperty: ResourceProperty, aResource : Resource, contextAdaptorInterface : AdaptorInterface)]
+@property
+# [protected ('getterAnnotation:'.concat(pythonAttributeName(aProperty, aResource)))]
+# [/protected]
+[if (not (nameAnnotation(aProperty) = ''))]
+[nameAnnotation(aProperty)/]
+[/if]
+[if (not (propertyDefinitionAnnotation(aProperty, aResource, contextAdaptorInterface) = ''))]
+[propertyDefinitionAnnotation(aProperty, aResource, contextAdaptorInterface)/]
+[/if]
+[if (not (descriptionAnnotation(aProperty) = ''))]
+[descriptionAnnotation(aProperty)/]
+[/if]
+[if (not (rdfCollectionTypeAnnotation(aProperty) = ''))]
+[rdfCollectionTypeAnnotation(aProperty)/]
+[/if]
+[if (not (occursAnnotation(aProperty) = ''))]
+[occursAnnotation(aProperty)/]
+[/if]
+[if (not (valueTypeAnnotation(aProperty) = ''))]
+[valueTypeAnnotation(aProperty)/]
+[/if]
+[if (not (representationAnnotation(aProperty) = ''))]
+[representationAnnotation(aProperty)/]
+[/if]
+[if (not (rangeAnnotation(aProperty, aResource, contextAdaptorInterface)= ''))]
+[rangeAnnotation(aProperty, aResource, contextAdaptorInterface)/]
+[/if]
+[if (not (readOnlyAnnotation(aProperty) = ''))]
+[readOnlyAnnotation(aProperty)/]
+[/if]
+[if (not (titleAnnotation(aProperty)= ''))]
+[titleAnnotation(aProperty)/]
+[/if]
+[if (not (isMemberPropertyAnnotation(aProperty)= ''))]
+[isMemberPropertyAnnotation(aProperty)/]
+[/if]
+[if (not (allowedValuesAnnotation(aProperty) = ''))]
+[allowedValuesAnnotation(aProperty)/]
+[/if]
+def [aProperty.pythonAttributeGetterMethodName(aResource)/](self):
+ # [protected ('getterInit:'.concat(pythonAttributeName(aProperty, aResource)))]
+ # [/protected]
+ return self._[aProperty.pythonAttributeName(aResource)/]
+[/template]
+
+[template public generateSetter(aProperty: ResourceProperty, aResource : Resource)]
+@[aProperty.pythonAttributeSetterMethodName(aResource)/].setter
+def [aProperty.pythonAttributeSetterMethodName(aResource)/](self, value: [aProperty.pythonAttributeTypeDeclaration()/]):
+ # [protected ('setterInit:'.concat(pythonAttributeName(aProperty, aResource)))]
+ # [/protected]
+ self._[aProperty.pythonAttributeName(aResource)/] = value
+ # [protected ('setterFinalize:'.concat(pythonAttributeName(aProperty, aResource)))]
+ # [/protected]
+[/template]
+
+
+[template public generateResource(aResource : Resource, contextAdaptorInterface : AdaptorInterface, defaultFilesPath : String, defaultPackageName : String)]
+[if (aResource.generate())]
+[file (aResource.pythonClassFullFileName(contextAdaptorInterface, defaultFilesPath, defaultPackageName), false, 'UTF-8')]
+[generateClassHeader(aResource, contextAdaptorInterface)/]
+
+[generateImports(aResource, contextAdaptorInterface, defaultPackageName)/]
+
+[generatePreClassCode(aResource, contextAdaptorInterface)/]
+
+[generateClassAnnotations(aResource)/]
+[generateClassDeclaration(aResource)/]
+ [generateClassAttributes(aResource)/]
+ [generateClassMethods(aResource)/]
+ [generateConstructor(aResource)/]
+ [generateAddToAttributeMethods(aResource)/]
+ [for (aProperty: ResourceProperty | ((aResource.resourceProperties->asSequence())->union(interfaceProperties(aResource))))]
+ [generateGetter(aProperty, aResource, contextAdaptorInterface)/]
+
+ [/for]
+ [for (aProperty: ResourceProperty | ((aResource.resourceProperties->asSequence())->union(interfaceProperties(aResource))))]
+ [generateSetter(aProperty, aResource)/]
+
+ [/for]
+[/file]
+[/if]
+[/template]
diff --git a/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/files/generateVocabularyConstants.mtl b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/files/generateVocabularyConstants.mtl
new file mode 100644
index 00000000..8b390cdc
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/files/generateVocabularyConstants.mtl
@@ -0,0 +1,51 @@
+[comment encoding = UTF-8 /]
+[comment
+/*
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License 1.0
+ * which is available at http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Simple
+ */
+/]
+[module generateVocabularyConstants('http://org.eclipse.lyo/oslc4j/adaptorInterface', 'http://org.eclipse.lyo/oslc4j/vocabulary', 'http://www.eclipse.org/emf/2002/Ecore')/]
+
+[import org::eclipse::lyo::oslc4j::codegenerator::python::services::fileServices/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::services::services/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::services::vocabularyServices/]
+
+[template public generateVocabularyConstants(aVocabulary : Vocabulary, anAdaptorInterface : AdaptorInterface, defaultFilesPath : String, defaultPackageName : String)]
+[let effectiveFilesPath : String = aVocabulary.filesBasePath(anAdaptorInterface, defaultFilesPath)]
+[let effectivePackageName : String = aVocabulary.pythonPackageNameForConstants(anAdaptorInterface, defaultPackageName)]
+[let rootInitFileName : String = aVocabulary.pythonFilesBasePath(anAdaptorInterface, effectiveFilesPath).concatenatePaths('__init__.py')]
+[file (rootInitFileName, false, 'UTF-8')]
+# [protected ('imports')]
+# [/protected]
+[/file]
+[/let]
+[let packageInitFileName : String = aVocabulary.pythonFilesBasePath(anAdaptorInterface, effectiveFilesPath).concatenatePaths(effectivePackageName.substituteAll('.', '/')).concatenatePaths('__init__.py')]
+[file (packageInitFileName, false, 'UTF-8')]
+# [protected ('imports')]
+# [/protected]
+[/file]
+[/let]
+[file (aVocabulary.pythonFullFileNameForConstants(null, effectiveFilesPath, effectivePackageName), false, 'UTF-8')]
+import rdflib
+
+# [protected ('imports')]
+# [/protected]
+
+[aVocabulary.vocabularyNamespaceConstantName()/] = rdflib.Namespace("[aVocabulary.namespaceURI/]")
+
+# [protected ('constants')]
+# [/protected]
+[/file]
+[/let]
+[/let]
+[/template]
diff --git a/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/main/Generate.java b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/main/Generate.java
new file mode 100644
index 00000000..3a3e6fbe
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/main/Generate.java
@@ -0,0 +1,415 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2012 Obeo.
+ * 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:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.lyo.oslc4j.codegenerator.python.main;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.acceleo.engine.event.IAcceleoTextGenerationListener;
+import org.eclipse.acceleo.engine.generation.strategy.IAcceleoGenerationStrategy;
+import org.eclipse.acceleo.engine.service.AbstractAcceleoGenerator;
+import org.eclipse.emf.common.util.BasicMonitor;
+import org.eclipse.emf.common.util.Monitor;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+
+/**
+ * Entry point of the 'Generate' generation module.
+ *
+ * @generated
+ */
+public class Generate extends AbstractAcceleoGenerator {
+ /**
+ * The name of the module.
+ *
+ * @generated
+ */
+ public static final String MODULE_FILE_NAME = "/org/eclipse/lyo/oslc4j/codegenerator/python/main/generate";
+
+ /**
+ * The name of the templates that are to be generated.
+ *
+ * @generated
+ */
+ public static final String[] TEMPLATE_NAMES = { "generate" };
+
+ /**
+ * The list of properties files from the launch parameters (Launch configuration).
+ *
+ * @generated
+ */
+ private List propertiesFiles = new ArrayList();
+
+ /**
+ * Allows the public constructor to be used. Note that a generator created
+ * this way cannot be used to launch generations before one of
+ * {@link #initialize(EObject, File, List)} or
+ * {@link #initialize(URI, File, List)} is called.
+ *
+ * The main reason for this constructor is to allow clients of this
+ * generation to call it from another Java file, as it allows for the
+ * retrieval of {@link #getProperties()} and
+ * {@link #getGenerationListeners()}.
+ *
+ *
+ * @generated
+ */
+ public Generate() {
+ // Empty implementation
+ }
+
+ /**
+ * This allows clients to instantiates a generator with all required information.
+ *
+ * @param modelURI
+ * URI where the model on which this generator will be used is located.
+ * @param targetFolder
+ * This will be used as the output folder for this generation : it will be the base path
+ * against which all file block URLs will be resolved.
+ * @param arguments
+ * If the template which will be called requires more than one argument taken from the model,
+ * pass them here.
+ * @throws IOException
+ * This can be thrown in three scenarios : the module cannot be found, it cannot be loaded, or
+ * the model cannot be loaded.
+ * @generated NOT
+ */
+ public Generate(URI modelURI, File targetFolder,
+ List extends Object> arguments) throws IOException {
+ initialize(modelURI, targetFolder, new ArrayList() {{add(targetFolder.getAbsolutePath());}});
+ }
+
+ /**
+ * This allows clients to instantiates a generator with all required information.
+ *
+ * @param model
+ * We'll iterate over the content of this element to find Objects matching the first parameter
+ * of the template we need to call.
+ * @param targetFolder
+ * This will be used as the output folder for this generation : it will be the base path
+ * against which all file block URLs will be resolved.
+ * @param arguments
+ * If the template which will be called requires more than one argument taken from the model,
+ * pass them here.
+ * @throws IOException
+ * This can be thrown in two scenarios : the module cannot be found, or it cannot be loaded.
+ * @generated NOT
+ */
+ public Generate(EObject model, File targetFolder,
+ List extends Object> arguments) throws IOException {
+ initialize(model, targetFolder, new ArrayList() {{add(targetFolder.getAbsolutePath());}});
+ }
+
+ /**
+ * This can be used to launch the generation from a standalone application.
+ *
+ * @param args
+ * Arguments of the generation.
+ * @generated
+ */
+ public static void main(String[] args) {
+ try {
+ if (args.length < 2) {
+ System.out.println("Arguments not valid : {model, folder}.");
+ } else {
+ URI modelURI = URI.createFileURI(args[0]);
+ File folder = new File(args[1]);
+
+ List arguments = new ArrayList();
+
+ /*
+ * If you want to change the content of this method, do NOT forget to change the "@generated"
+ * tag in the Javadoc of this method to "@generated NOT". Without this new tag, any compilation
+ * of the Acceleo module with the main template that has caused the creation of this class will
+ * revert your modifications.
+ */
+
+ /*
+ * Add in this list all the arguments used by the starting point of the generation
+ * If your main template is called on an element of your model and a String, you can
+ * add in "arguments" this "String" attribute.
+ */
+
+ Generate generator = new Generate(modelURI, folder, arguments);
+
+ /*
+ * Add the properties from the launch arguments.
+ * If you want to programmatically add new properties, add them in "propertiesFiles"
+ * You can add the absolute path of a properties files, or even a project relative path.
+ * If you want to add another "protocol" for your properties files, please override
+ * "getPropertiesLoaderService(AcceleoService)" in order to return a new property loader.
+ * The behavior of the properties loader service is explained in the Acceleo documentation
+ * (Help -> Help Contents).
+ */
+
+ for (int i = 2; i < args.length; i++) {
+ generator.addPropertiesFile(args[i]);
+ }
+
+ generator.doGenerate(new BasicMonitor());
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Launches the generation described by this instance.
+ *
+ * @param monitor
+ * This will be used to display progress information to the user.
+ * @throws IOException
+ * This will be thrown if any of the output files cannot be saved to disk.
+ * @generated
+ */
+ @Override
+ public void doGenerate(Monitor monitor) throws IOException {
+ /*
+ * TODO if you wish to change the generation as a whole, override this. The default behavior should
+ * be sufficient in most cases. If you want to change the content of this method, do NOT forget to
+ * change the "@generated" tag in the Javadoc of this method to "@generated NOT". Without this new tag,
+ * any compilation of the Acceleo module with the main template that has caused the creation of this
+ * class will revert your modifications. If you encounter a problem with an unresolved proxy during the
+ * generation, you can remove the comments in the following instructions to check for problems. Please
+ * note that those instructions may have a significant impact on the performances.
+ */
+
+ //org.eclipse.emf.ecore.util.EcoreUtil.resolveAll(model);
+
+ /*
+ * If you want to check for potential errors in your models before the launch of the generation, you
+ * use the code below.
+ */
+
+ //if (model != null && model.eResource() != null) {
+ // List errors = model.eResource().getErrors();
+ // for (org.eclipse.emf.ecore.resource.Resource.Diagnostic diagnostic : errors) {
+ // System.err.println(diagnostic.toString());
+ // }
+ //}
+
+ super.doGenerate(monitor);
+ }
+
+ /**
+ * If this generator needs to listen to text generation events, listeners can be returned from here.
+ *
+ * @return List of listeners that are to be notified when text is generated through this launch.
+ * @generated
+ */
+ @Override
+ public List getGenerationListeners() {
+ List listeners = super.getGenerationListeners();
+ /*
+ * TODO if you need to listen to generation event, add listeners to the list here. If you want to change
+ * the content of this method, do NOT forget to change the "@generated" tag in the Javadoc of this method
+ * to "@generated NOT". Without this new tag, any compilation of the Acceleo module with the main template
+ * that has caused the creation of this class will revert your modifications.
+ */
+ return listeners;
+ }
+
+ /**
+ * If you need to change the way files are generated, this is your entry point.
+ *
+ * The default is {@link org.eclipse.acceleo.engine.generation.strategy.DefaultStrategy}; it generates
+ * files on the fly. If you only need to preview the results, return a new
+ * {@link org.eclipse.acceleo.engine.generation.strategy.PreviewStrategy}. Both of these aren't aware of
+ * the running Eclipse and can be used standalone.
+ *
+ *
+ * If you need the file generation to be aware of the workspace (A typical example is when you wanna
+ * override files that are under clear case or any other VCS that could forbid the overriding), then
+ * return a new {@link org.eclipse.acceleo.engine.generation.strategy.WorkspaceAwareStrategy}.
+ * Note, however, that this cannot be used standalone.
+ *
+ *
+ * All three of these default strategies support merging through JMerge.
+ *
+ *
+ * @return The generation strategy that is to be used for generations launched through this launcher.
+ * @generated
+ */
+ @Override
+ public IAcceleoGenerationStrategy getGenerationStrategy() {
+ return super.getGenerationStrategy();
+ }
+
+ /**
+ * This will be called in order to find and load the module that will be launched through this launcher.
+ * We expect this name not to contain file extension, and the module to be located beside the launcher.
+ *
+ * @return The name of the module that is to be launched.
+ * @generated
+ */
+ @Override
+ public String getModuleName() {
+ return MODULE_FILE_NAME;
+ }
+
+ /**
+ * If the module(s) called by this launcher require properties files, return their qualified path from
+ * here.Take note that the first added properties files will take precedence over subsequent ones if they
+ * contain conflicting keys.
+ *
+ * @return The list of properties file we need to add to the generation context.
+ * @see java.util.ResourceBundle#getBundle(String)
+ * @generated
+ */
+ @Override
+ public List getProperties() {
+ /*
+ * If you want to change the content of this method, do NOT forget to change the "@generated"
+ * tag in the Javadoc of this method to "@generated NOT". Without this new tag, any compilation
+ * of the Acceleo module with the main template that has caused the creation of this class will
+ * revert your modifications.
+ */
+
+ /*
+ * TODO if your generation module requires access to properties files, add their qualified path to the list here.
+ *
+ * Properties files can be located in an Eclipse plug-in or in the file system (all Acceleo projects are Eclipse
+ * plug-in). In order to use properties files located in an Eclipse plugin, you need to add the path of the properties
+ * files to the "propertiesFiles" list:
+ *
+ * final String prefix = "platform:/plugin/";
+ * final String pluginName = "org.eclipse.acceleo.module.sample";
+ * final String packagePath = "/org/eclipse/acceleo/module/sample/properties/";
+ * final String fileName = "default.properties";
+ * propertiesFiles.add(prefix + pluginName + packagePath + fileName);
+ *
+ * With this mechanism, you can load properties files from your plugin or from another plugin.
+ *
+ * You may want to load properties files from the file system, for that you need to add the absolute path of the file:
+ *
+ * propertiesFiles.add("C:\Users\MyName\MyFile.properties");
+ *
+ * If you want to let your users add properties files located in the same folder as the model:
+ *
+ * if (EMFPlugin.IS_ECLIPSE_RUNNING && model != null && model.eResource() != null) {
+ * propertiesFiles.addAll(AcceleoEngineUtils.getPropertiesFilesNearModel(model.eResource()));
+ * }
+ *
+ * To learn more about Properties Files, have a look at the Acceleo documentation (Help -> Help Contents).
+ */
+ return propertiesFiles;
+ }
+
+ /**
+ * Adds a properties file in the list of properties files.
+ *
+ * @param propertiesFile
+ * The properties file to add.
+ * @generated
+ * @since 3.1
+ */
+ @Override
+ public void addPropertiesFile(String propertiesFile) {
+ this.propertiesFiles.add(propertiesFile);
+ }
+
+ /**
+ * This will be used to get the list of templates that are to be launched by this launcher.
+ *
+ * @return The list of templates to call on the module {@link #getModuleName()}.
+ * @generated
+ */
+ @Override
+ public String[] getTemplateNames() {
+ return TEMPLATE_NAMES;
+ }
+
+ /**
+ * This can be used to update the resource set's package registry with all needed EPackages.
+ *
+ * @param resourceSet
+ * The resource set which registry has to be updated.
+ * @generated
+ */
+ @Override
+ public void registerPackages(ResourceSet resourceSet) {
+ super.registerPackages(resourceSet);
+ if (!isInWorkspace(org.eclipse.emf.ecore.EcorePackage.class)) {
+ resourceSet.getPackageRegistry().put(org.eclipse.emf.ecore.EcorePackage.eINSTANCE.getNsURI(), org.eclipse.emf.ecore.EcorePackage.eINSTANCE);
+ }
+
+ /*
+ * If you want to change the content of this method, do NOT forget to change the "@generated"
+ * tag in the Javadoc of this method to "@generated NOT". Without this new tag, any compilation
+ * of the Acceleo module with the main template that has caused the creation of this class will
+ * revert your modifications.
+ */
+
+ /*
+ * If you need additional package registrations, you can register them here. The following line
+ * (in comment) is an example of the package registration for UML.
+ *
+ * You can use the method "isInWorkspace(Class c)" to check if the package that you are about to
+ * register is in the workspace.
+ *
+ * To register a package properly, please follow the following conventions:
+ *
+ * If the package is located in another plug-in, already installed in Eclipse. The following content should
+ * have been generated at the beginning of this method. Do not register the package using this mechanism if
+ * the metamodel is located in the workspace.
+ *
+ * if (!isInWorkspace(UMLPackage.class)) {
+ * // The normal package registration if your metamodel is in a plugin.
+ * resourceSet.getPackageRegistry().put(UMLPackage.eNS_URI, UMLPackage.eINSTANCE);
+ * }
+ *
+ * If the package is located in another project in your workspace, the plugin containing the package has not
+ * been register by EMF and Acceleo should register it automatically. If you want to use the generator in
+ * stand alone, the regular registration (seen a couple lines before) is needed.
+ *
+ * To learn more about Package Registration, have a look at the Acceleo documentation (Help -> Help Contents).
+ */
+ }
+
+ /**
+ * This can be used to update the resource set's resource factory registry with all needed factories.
+ *
+ * @param resourceSet
+ * The resource set which registry has to be updated.
+ * @generated
+ */
+ @Override
+ public void registerResourceFactories(ResourceSet resourceSet) {
+ super.registerResourceFactories(resourceSet);
+ /*
+ * If you want to change the content of this method, do NOT forget to change the "@generated"
+ * tag in the Javadoc of this method to "@generated NOT". Without this new tag, any compilation
+ * of the Acceleo module with the main template that has caused the creation of this class will
+ * revert your modifications.
+ */
+
+ /*
+ * TODO If you need additional resource factories registrations, you can register them here. the following line
+ * (in comment) is an example of the resource factory registration.
+ *
+ * If you want to use the generator in stand alone, the resource factory registration will be required.
+ *
+ * To learn more about the registration of Resource Factories, have a look at the Acceleo documentation (Help -> Help Contents).
+ */
+
+ // resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put(XyzResource.FILE_EXTENSION, XyzResource.Factory.INSTANCE);
+
+ /*
+ * Some metamodels require a very complex setup for standalone usage. For example, if you want to use a generator
+ * targetting UML models in standalone, you NEED to use the following:
+ */
+ // UMLResourcesUtil.init(resourceSet)
+ }
+
+}
diff --git a/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/main/GenerateSpecification.java b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/main/GenerateSpecification.java
new file mode 100644
index 00000000..734527b4
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/main/GenerateSpecification.java
@@ -0,0 +1,415 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2012 Obeo.
+ * 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:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.lyo.oslc4j.codegenerator.python.main;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.acceleo.engine.event.IAcceleoTextGenerationListener;
+import org.eclipse.acceleo.engine.generation.strategy.IAcceleoGenerationStrategy;
+import org.eclipse.acceleo.engine.service.AbstractAcceleoGenerator;
+import org.eclipse.emf.common.util.BasicMonitor;
+import org.eclipse.emf.common.util.Monitor;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+
+/**
+ * Entry point of the 'GenerateSpecification' generation module.
+ *
+ * @generated
+ */
+public class GenerateSpecification extends AbstractAcceleoGenerator {
+ /**
+ * The name of the module.
+ *
+ * @generated
+ */
+ public static final String MODULE_FILE_NAME = "/org/eclipse/lyo/oslc4j/codegenerator/python/main/generateSpecification";
+
+ /**
+ * The name of the templates that are to be generated.
+ *
+ * @generated
+ */
+ public static final String[] TEMPLATE_NAMES = { "generateSpecification" };
+
+ /**
+ * The list of properties files from the launch parameters (Launch configuration).
+ *
+ * @generated
+ */
+ private List propertiesFiles = new ArrayList();
+
+ /**
+ * Allows the public constructor to be used. Note that a generator created
+ * this way cannot be used to launch generations before one of
+ * {@link #initialize(EObject, File, List)} or
+ * {@link #initialize(URI, File, List)} is called.
+ *
+ * The main reason for this constructor is to allow clients of this
+ * generation to call it from another Java file, as it allows for the
+ * retrieval of {@link #getProperties()} and
+ * {@link #getGenerationListeners()}.
+ *
+ *
+ * @generated
+ */
+ public GenerateSpecification() {
+ // Empty implementation
+ }
+
+ /**
+ * This allows clients to instantiates a generator with all required information.
+ *
+ * @param modelURI
+ * URI where the model on which this generator will be used is located.
+ * @param targetFolder
+ * This will be used as the output folder for this generation : it will be the base path
+ * against which all file block URLs will be resolved.
+ * @param arguments
+ * If the template which will be called requires more than one argument taken from the model,
+ * pass them here.
+ * @throws IOException
+ * This can be thrown in three scenarios : the module cannot be found, it cannot be loaded, or
+ * the model cannot be loaded.
+ * @generated
+ */
+ public GenerateSpecification(URI modelURI, File targetFolder,
+ List extends Object> arguments) throws IOException {
+ initialize(modelURI, targetFolder, arguments);
+ }
+
+ /**
+ * This allows clients to instantiates a generator with all required information.
+ *
+ * @param model
+ * We'll iterate over the content of this element to find Objects matching the first parameter
+ * of the template we need to call.
+ * @param targetFolder
+ * This will be used as the output folder for this generation : it will be the base path
+ * against which all file block URLs will be resolved.
+ * @param arguments
+ * If the template which will be called requires more than one argument taken from the model,
+ * pass them here.
+ * @throws IOException
+ * This can be thrown in two scenarios : the module cannot be found, or it cannot be loaded.
+ * @generated
+ */
+ public GenerateSpecification(EObject model, File targetFolder,
+ List extends Object> arguments) throws IOException {
+ initialize(model, targetFolder, arguments);
+ }
+
+ /**
+ * This can be used to launch the generation from a standalone application.
+ *
+ * @param args
+ * Arguments of the generation.
+ * @generated
+ */
+ public static void main(String[] args) {
+ try {
+ if (args.length < 2) {
+ System.out.println("Arguments not valid : {model, folder}.");
+ } else {
+ URI modelURI = URI.createFileURI(args[0]);
+ File folder = new File(args[1]);
+
+ List arguments = new ArrayList();
+
+ /*
+ * If you want to change the content of this method, do NOT forget to change the "@generated"
+ * tag in the Javadoc of this method to "@generated NOT". Without this new tag, any compilation
+ * of the Acceleo module with the main template that has caused the creation of this class will
+ * revert your modifications.
+ */
+
+ /*
+ * Add in this list all the arguments used by the starting point of the generation
+ * If your main template is called on an element of your model and a String, you can
+ * add in "arguments" this "String" attribute.
+ */
+
+ GenerateSpecification generator = new GenerateSpecification(modelURI, folder, arguments);
+
+ /*
+ * Add the properties from the launch arguments.
+ * If you want to programmatically add new properties, add them in "propertiesFiles"
+ * You can add the absolute path of a properties files, or even a project relative path.
+ * If you want to add another "protocol" for your properties files, please override
+ * "getPropertiesLoaderService(AcceleoService)" in order to return a new property loader.
+ * The behavior of the properties loader service is explained in the Acceleo documentation
+ * (Help -> Help Contents).
+ */
+
+ for (int i = 2; i < args.length; i++) {
+ generator.addPropertiesFile(args[i]);
+ }
+
+ generator.doGenerate(new BasicMonitor());
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Launches the generation described by this instance.
+ *
+ * @param monitor
+ * This will be used to display progress information to the user.
+ * @throws IOException
+ * This will be thrown if any of the output files cannot be saved to disk.
+ * @generated
+ */
+ @Override
+ public void doGenerate(Monitor monitor) throws IOException {
+ /*
+ * TODO if you wish to change the generation as a whole, override this. The default behavior should
+ * be sufficient in most cases. If you want to change the content of this method, do NOT forget to
+ * change the "@generated" tag in the Javadoc of this method to "@generated NOT". Without this new tag,
+ * any compilation of the Acceleo module with the main template that has caused the creation of this
+ * class will revert your modifications. If you encounter a problem with an unresolved proxy during the
+ * generation, you can remove the comments in the following instructions to check for problems. Please
+ * note that those instructions may have a significant impact on the performances.
+ */
+
+ //org.eclipse.emf.ecore.util.EcoreUtil.resolveAll(model);
+
+ /*
+ * If you want to check for potential errors in your models before the launch of the generation, you
+ * use the code below.
+ */
+
+ //if (model != null && model.eResource() != null) {
+ // List errors = model.eResource().getErrors();
+ // for (org.eclipse.emf.ecore.resource.Resource.Diagnostic diagnostic : errors) {
+ // System.err.println(diagnostic.toString());
+ // }
+ //}
+
+ super.doGenerate(monitor);
+ }
+
+ /**
+ * If this generator needs to listen to text generation events, listeners can be returned from here.
+ *
+ * @return List of listeners that are to be notified when text is generated through this launch.
+ * @generated
+ */
+ @Override
+ public List getGenerationListeners() {
+ List listeners = super.getGenerationListeners();
+ /*
+ * TODO if you need to listen to generation event, add listeners to the list here. If you want to change
+ * the content of this method, do NOT forget to change the "@generated" tag in the Javadoc of this method
+ * to "@generated NOT". Without this new tag, any compilation of the Acceleo module with the main template
+ * that has caused the creation of this class will revert your modifications.
+ */
+ return listeners;
+ }
+
+ /**
+ * If you need to change the way files are generated, this is your entry point.
+ *
+ * The default is {@link org.eclipse.acceleo.engine.generation.strategy.DefaultStrategy}; it generates
+ * files on the fly. If you only need to preview the results, return a new
+ * {@link org.eclipse.acceleo.engine.generation.strategy.PreviewStrategy}. Both of these aren't aware of
+ * the running Eclipse and can be used standalone.
+ *
+ *
+ * If you need the file generation to be aware of the workspace (A typical example is when you wanna
+ * override files that are under clear case or any other VCS that could forbid the overriding), then
+ * return a new {@link org.eclipse.acceleo.engine.generation.strategy.WorkspaceAwareStrategy}.
+ * Note, however, that this cannot be used standalone.
+ *
+ *
+ * All three of these default strategies support merging through JMerge.
+ *
+ *
+ * @return The generation strategy that is to be used for generations launched through this launcher.
+ * @generated
+ */
+ @Override
+ public IAcceleoGenerationStrategy getGenerationStrategy() {
+ return super.getGenerationStrategy();
+ }
+
+ /**
+ * This will be called in order to find and load the module that will be launched through this launcher.
+ * We expect this name not to contain file extension, and the module to be located beside the launcher.
+ *
+ * @return The name of the module that is to be launched.
+ * @generated
+ */
+ @Override
+ public String getModuleName() {
+ return MODULE_FILE_NAME;
+ }
+
+ /**
+ * If the module(s) called by this launcher require properties files, return their qualified path from
+ * here.Take note that the first added properties files will take precedence over subsequent ones if they
+ * contain conflicting keys.
+ *
+ * @return The list of properties file we need to add to the generation context.
+ * @see java.util.ResourceBundle#getBundle(String)
+ * @generated
+ */
+ @Override
+ public List getProperties() {
+ /*
+ * If you want to change the content of this method, do NOT forget to change the "@generated"
+ * tag in the Javadoc of this method to "@generated NOT". Without this new tag, any compilation
+ * of the Acceleo module with the main template that has caused the creation of this class will
+ * revert your modifications.
+ */
+
+ /*
+ * TODO if your generation module requires access to properties files, add their qualified path to the list here.
+ *
+ * Properties files can be located in an Eclipse plug-in or in the file system (all Acceleo projects are Eclipse
+ * plug-in). In order to use properties files located in an Eclipse plugin, you need to add the path of the properties
+ * files to the "propertiesFiles" list:
+ *
+ * final String prefix = "platform:/plugin/";
+ * final String pluginName = "org.eclipse.acceleo.module.sample";
+ * final String packagePath = "/org/eclipse/acceleo/module/sample/properties/";
+ * final String fileName = "default.properties";
+ * propertiesFiles.add(prefix + pluginName + packagePath + fileName);
+ *
+ * With this mechanism, you can load properties files from your plugin or from another plugin.
+ *
+ * You may want to load properties files from the file system, for that you need to add the absolute path of the file:
+ *
+ * propertiesFiles.add("C:\Users\MyName\MyFile.properties");
+ *
+ * If you want to let your users add properties files located in the same folder as the model:
+ *
+ * if (EMFPlugin.IS_ECLIPSE_RUNNING && model != null && model.eResource() != null) {
+ * propertiesFiles.addAll(AcceleoEngineUtils.getPropertiesFilesNearModel(model.eResource()));
+ * }
+ *
+ * To learn more about Properties Files, have a look at the Acceleo documentation (Help -> Help Contents).
+ */
+ return propertiesFiles;
+ }
+
+ /**
+ * Adds a properties file in the list of properties files.
+ *
+ * @param propertiesFile
+ * The properties file to add.
+ * @generated
+ * @since 3.1
+ */
+ @Override
+ public void addPropertiesFile(String propertiesFile) {
+ this.propertiesFiles.add(propertiesFile);
+ }
+
+ /**
+ * This will be used to get the list of templates that are to be launched by this launcher.
+ *
+ * @return The list of templates to call on the module {@link #getModuleName()}.
+ * @generated
+ */
+ @Override
+ public String[] getTemplateNames() {
+ return TEMPLATE_NAMES;
+ }
+
+ /**
+ * This can be used to update the resource set's package registry with all needed EPackages.
+ *
+ * @param resourceSet
+ * The resource set which registry has to be updated.
+ * @generated
+ */
+ @Override
+ public void registerPackages(ResourceSet resourceSet) {
+ super.registerPackages(resourceSet);
+ if (!isInWorkspace(org.eclipse.emf.ecore.EcorePackage.class)) {
+ resourceSet.getPackageRegistry().put(org.eclipse.emf.ecore.EcorePackage.eINSTANCE.getNsURI(), org.eclipse.emf.ecore.EcorePackage.eINSTANCE);
+ }
+
+ /*
+ * If you want to change the content of this method, do NOT forget to change the "@generated"
+ * tag in the Javadoc of this method to "@generated NOT". Without this new tag, any compilation
+ * of the Acceleo module with the main template that has caused the creation of this class will
+ * revert your modifications.
+ */
+
+ /*
+ * If you need additional package registrations, you can register them here. The following line
+ * (in comment) is an example of the package registration for UML.
+ *
+ * You can use the method "isInWorkspace(Class c)" to check if the package that you are about to
+ * register is in the workspace.
+ *
+ * To register a package properly, please follow the following conventions:
+ *
+ * If the package is located in another plug-in, already installed in Eclipse. The following content should
+ * have been generated at the beginning of this method. Do not register the package using this mechanism if
+ * the metamodel is located in the workspace.
+ *
+ * if (!isInWorkspace(UMLPackage.class)) {
+ * // The normal package registration if your metamodel is in a plugin.
+ * resourceSet.getPackageRegistry().put(UMLPackage.eNS_URI, UMLPackage.eINSTANCE);
+ * }
+ *
+ * If the package is located in another project in your workspace, the plugin containing the package has not
+ * been register by EMF and Acceleo should register it automatically. If you want to use the generator in
+ * stand alone, the regular registration (seen a couple lines before) is needed.
+ *
+ * To learn more about Package Registration, have a look at the Acceleo documentation (Help -> Help Contents).
+ */
+ }
+
+ /**
+ * This can be used to update the resource set's resource factory registry with all needed factories.
+ *
+ * @param resourceSet
+ * The resource set which registry has to be updated.
+ * @generated
+ */
+ @Override
+ public void registerResourceFactories(ResourceSet resourceSet) {
+ super.registerResourceFactories(resourceSet);
+ /*
+ * If you want to change the content of this method, do NOT forget to change the "@generated"
+ * tag in the Javadoc of this method to "@generated NOT". Without this new tag, any compilation
+ * of the Acceleo module with the main template that has caused the creation of this class will
+ * revert your modifications.
+ */
+
+ /*
+ * TODO If you need additional resource factories registrations, you can register them here. the following line
+ * (in comment) is an example of the resource factory registration.
+ *
+ * If you want to use the generator in stand alone, the resource factory registration will be required.
+ *
+ * To learn more about the registration of Resource Factories, have a look at the Acceleo documentation (Help -> Help Contents).
+ */
+
+ // resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put(XyzResource.FILE_EXTENSION, XyzResource.Factory.INSTANCE);
+
+ /*
+ * Some metamodels require a very complex setup for standalone usage. For example, if you want to use a generator
+ * targetting UML models in standalone, you NEED to use the following:
+ */
+ // UMLResourcesUtil.init(resourceSet)
+ }
+
+}
diff --git a/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/main/generate.mtl b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/main/generate.mtl
new file mode 100644
index 00000000..d7f2c415
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/main/generate.mtl
@@ -0,0 +1,79 @@
+[comment encoding = UTF-8 /]
+[comment
+/*
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License 1.0
+ * which is available at http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Simple
+ */
+/]
+[module generate('http://org.eclipse.lyo/oslc4j/adaptorInterface', 'http://org.eclipse.lyo/oslc4j/vocabulary', 'http://www.eclipse.org/emf/2002/Ecore')]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::services::resourceServices/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::services::services/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::services::adaptorInterfaceServices/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::staticFiles::generateLicenseFiles/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::services::fileServices/]
+
+
+[import org::eclipse::lyo::oslc4j::codegenerator::python::files::generateAdaptorPackageInfo/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::files::generateDomainSpecificationConstants/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::files::generateVocabularyConstants/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::files::generateResource/]
+
+[import org::eclipse::lyo::oslc4j::codegenerator::python::config::generateConfigFiles/]
+
+[template public generateCommon(anAdaptorInterface : AdaptorInterface)]
+[anAdaptorInterface.generateLicenseFiles() /]
+[anAdaptorInterface.specification.generateConfigFiles() /]
+[/template]
+
+[comment Group the resources that need to be generated into their specific destination folders. For each such folder, generate a packageInfo class that lists their namespaces./]
+[template public generateForPackageInfo(anAdaptorInterface : AdaptorInterface)]
+[let resources: Set(Resource) = relevantResources(anAdaptorInterface)->select(r: Resource | anAdaptorInterface.generateIfFromImportedModels(r.oclAsType(EObject)))]
+[let uniqueFolderPaths: Set(String) = resources->collect(r: Resource | r.pythonClassFullFolderName(anAdaptorInterface, null, null))->asSet()]
+[for (uniqueFolderPath: String | uniqueFolderPaths)]
+ [let resourcesOnSameFolderPath: Set(Resource) = resources->select(r: Resource | r.pythonClassFullFolderName(anAdaptorInterface, null, null) = uniqueFolderPath)]
+ [generateAdaptorPackageInfo(resourcesOnSameFolderPath, anAdaptorInterface, null, null)/]
+ [/let]
+[/for]
+[/let]
+[/let]
+[/template]
+
+[template public generateForRelevantDomainSpecifications(anAdaptorInterface : AdaptorInterface)]
+[for (aDomainSpecification: DomainSpecification | relevantDomainSpecifications(anAdaptorInterface)
+ ->select(o: DomainSpecification | anAdaptorInterface.generateIfFromImportedModels(o.oclAsType(EObject))))]
+ [aDomainSpecification.generateDomainSpecificationConstants(anAdaptorInterface, null, null)/]
+[/for]
+[/template]
+
+[template public generateForRelevantVocabularies(anAdaptorInterface : AdaptorInterface)]
+[for (aVocabulary: Vocabulary | relevantVocabularies(anAdaptorInterface)
+ ->select(o: Vocabulary | anAdaptorInterface.generateIfFromImportedModels(o.oclAsType(EObject))))]
+ [aVocabulary.generateVocabularyConstants(anAdaptorInterface, null, null)/]
+[/for]
+[/template]
+
+[template public generateForRelevantResources(anAdaptorInterface : AdaptorInterface)]
+[for (aResource: Resource | relevantResources(anAdaptorInterface)
+ ->select(o: Resource | anAdaptorInterface.generateIfFromImportedModels(o.oclAsType(EObject))))]
+ [aResource.generateResource(anAdaptorInterface, null, null) /]
+[/for]
+[/template]
+
+[template public generate(anAdaptorInterface : AdaptorInterface, targetFolder : String)]
+[comment @main/]
+[setTargetFolder(targetFolder)/]
+[generateCommon(anAdaptorInterface)/]
+[generateForPackageInfo(anAdaptorInterface)/]
+[generateForRelevantDomainSpecifications(anAdaptorInterface)/]
+[generateForRelevantVocabularies(anAdaptorInterface)/]
+[generateForRelevantResources(anAdaptorInterface)/]
+[/template]
diff --git a/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/main/generateSpecification.mtl b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/main/generateSpecification.mtl
new file mode 100644
index 00000000..0bbd6fc5
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/main/generateSpecification.mtl
@@ -0,0 +1,77 @@
+[comment encoding = UTF-8 /]
+[comment
+/*
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License 1.0
+ * which is available at http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Simple
+ */
+/]
+[module generateSpecification('http://org.eclipse.lyo/oslc4j/adaptorInterface', 'http://org.eclipse.lyo/oslc4j/vocabulary','http://www.eclipse.org/emf/2002/Ecore')]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::services::adaptorInterfaceServices/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::staticFiles::generateLicenseFiles/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::services::services/]
+
+[import org::eclipse::lyo::oslc4j::codegenerator::python::services::resourceServices/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::files::generateAdaptorPackageInfo/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::files::generateDomainSpecificationConstants/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::files::generateVocabularyConstants/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::files::generateResource/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::config::generateConfigFiles/]
+
+[comment same/]
+[query public canGenerate(aSpecification : Specification) : Boolean =
+not(
+aSpecification.configuration.oclIsUndefined()
+ or(aSpecification.configuration.generalConfiguration.filesBasePath.isNullOrEmpty())
+ or(aSpecification.configuration.generalConfiguration.javaBasePackageName.isNullOrEmpty())
+)
+/]
+
+[template public generateSpecification(aSpecification : Specification)]
+[comment @main/]
+[if (canGenerate(aSpecification))]
+[let defaultFilesPath : String = aSpecification.configuration.generalConfiguration.filesBasePath]
+[let defaultPackageName : String = aSpecification.configuration.generalConfiguration.javaBasePackageName]
+ [aSpecification.generateLicenseFiles() /]
+ [aSpecification.generateConfigFiles() /]
+ [file (aSpecification.pythonFilesBasePath(null, defaultFilesPath).concatenatePaths('__init__.py'), false, 'UTF-8')]
+# [protected ('imports')]
+# [/protected]
+ [/file]
+
+ [for (aDomainSpecification: DomainSpecification | aSpecification.relevantDomainSpecifications()
+ ->select(d: DomainSpecification | aSpecification.generateIfFromImportedModels(d.oclAsType(EObject))))]
+ [aDomainSpecification.generateDomainSpecificationConstants(defaultFilesPath, defaultPackageName)/]
+ [/for]
+
+ [for (aVocabulary: Vocabulary | aSpecification.relevantVocabularies()
+ ->select(v: Vocabulary | aSpecification.generateIfFromImportedModels(v.oclAsType(EObject))))]
+ [aVocabulary.generateVocabularyConstants(null, defaultFilesPath, defaultPackageName)/]
+ [/for]
+
+ [for (aResource: Resource | aSpecification.relevantResources()
+ ->select(r: Resource | aSpecification.generateIfFromImportedModels(r.oclAsType(EObject))))]
+ [aResource.generateResource(null, defaultFilesPath, defaultPackageName) /]
+ [/for]
+
+ [let resources: Set(Resource) = aSpecification.relevantResources()->select(r: Resource | aSpecification.generateIfFromImportedModels(r.oclAsType(EObject)))]
+ [let uniqueFolderPaths: Set(String) = resources->collect(r: Resource | r.pythonClassFullFolderName(null, defaultFilesPath, defaultPackageName))->asSet()]
+ [for (uniqueFolderPath: String | uniqueFolderPaths)]
+ [let resourcesOnSameFolderPath: Set(Resource) = resources->select(r: Resource | r.pythonClassFullFolderName(null, defaultFilesPath, defaultPackageName) = uniqueFolderPath)]
+ [generateAdaptorPackageInfo(resourcesOnSameFolderPath, defaultFilesPath, defaultPackageName)/]
+ [/let]
+ [/for]
+ [/let]
+ [/let]
+[/let]
+[/let]
+[/if]
+[/template]
diff --git a/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/services/FileServices.java b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/services/FileServices.java
new file mode 100644
index 00000000..10f3f155
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/services/FileServices.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License 1.0
+ * which is available at http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Simple
+ */
+package org.eclipse.lyo.oslc4j.codegenerator.python.services;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class FileServices {
+
+ private static String targetFolder;
+
+ public void setTargetFolder (String path) {
+ targetFolder = path;
+ }
+
+ public boolean fileExists(String filepath) {
+ Path p = Paths.get(targetFolder, filepath);
+ p.normalize();
+ File f = new File(p.toString());
+ return f.exists();
+ }
+}
diff --git a/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/services/adaptorInterfaceServices.mtl b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/services/adaptorInterfaceServices.mtl
new file mode 100644
index 00000000..b3a59c3a
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/services/adaptorInterfaceServices.mtl
@@ -0,0 +1,161 @@
+[comment encoding = UTF-8 /]
+[comment
+/*
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License 1.0
+ * which is available at http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Simple
+ */
+/]
+[module adaptorInterfaceServices('http://org.eclipse.lyo/oslc4j/adaptorInterface', 'http://org.eclipse.lyo/oslc4j/vocabulary')/]
+
+[import org::eclipse::lyo::oslc4j::codegenerator::python::services::vocabularyServices/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::services::domainSpecificationServices/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::services::resourceServices/]
+
+[query public serviceProviders(anAdaptorInterface : AdaptorInterface) : Sequence(ServiceProvider) =
+(if (not anAdaptorInterface.serviceProviderCatalog.oclIsUndefined()) then
+ anAdaptorInterface.serviceProviderCatalog.serviceProviders
+else
+ Sequence{}
+endif)
+/]
+
+[query public servicedResources(anAdaptorInterface : AdaptorInterface) : Set(Resource) =
+anAdaptorInterface.serviceProviders()->collectNested(aServiceProvider : ServiceProvider |
+ servicedResources(aServiceProvider)
+)->flatten()->asSet()
+->union(
+ anAdaptorInterface.webServices->collectNested(aWebService : WebService |
+ servicedResources(aWebService)
+ )->flatten()->asSet()
+)
+/]
+
+[query public relevantResources(anAdaptorInterface : AdaptorInterface) : Set(Resource) =
+anAdaptorInterface.serviceProviders()->collectNested(aServiceProvider : ServiceProvider |
+ relevantResources(aServiceProvider)
+)->flatten()->asSet()
+->union(
+ anAdaptorInterface.requiredAdaptors->collectNested(aRequiredAdaptor : RequiredAdaptor |
+ relevantResources(aRequiredAdaptor)
+ )->flatten()->asSet()
+)
+/]
+
+[query public relevantResources(aSpecification : Specification) : Set(Resource) =
+ (aSpecification.domainSpecifications.resources
+ ->union(aSpecification.domainSpecifications.resources.allRelatedResources()))->flatten()->asSet()
+/]
+
+[query public servicedResources(aWebService: WebService) : Set(Resource) =
+aWebService.resourceTypes->asSet()
+/]
+
+[query public relevantDomainSpecifications(anAdaptorInterface : AdaptorInterface) : Set(DomainSpecification) =
+anAdaptorInterface.serviceProviders()->collectNested(aServiceProvider : ServiceProvider |
+ relevantDomainSpecifications(aServiceProvider)
+)->flatten()->asSet()
+->union(
+ anAdaptorInterface.requiredAdaptors->collectNested(aRequiredAdaptor : RequiredAdaptor |
+ relevantDomainSpecifications(aRequiredAdaptor)
+ )->flatten()->asSet()
+)
+/]
+
+[query public relevantDomainSpecifications(aSpecification : Specification) : Set(DomainSpecification) =
+aSpecification.domainSpecifications->union(
+ relevantResources(aSpecification)->collectNested(aResource : Resource | aResource.definingDomainSpecification())->flatten()->asSet()
+)
+/]
+
+[query public relevantVocabularies(anAdaptorInterface : AdaptorInterface) : Set(Vocabulary) =
+anAdaptorInterface.relevantDomainSpecifications()->collectNested(aDomainSpecification : DomainSpecification |
+ relevantVocabularies(aDomainSpecification)
+)->flatten()->asSet()
+/]
+[query public relevantVocabularies(aDomainSpecification: DomainSpecification) : Set(Vocabulary) =
+aDomainSpecification.resources->select(not describes.oclIsUndefined())->collect(aResource : Resource | definingVocabulary(aResource.describes))
+->union(
+ aDomainSpecification.resourceProperties->select(not propertyDefinition.oclIsUndefined())->collect(aResourceProperty : ResourceProperty | definingVocabulary(aResourceProperty.propertyDefinition))
+)->asSet()
+/]
+
+[query public relevantVocabularies(aSpecification : Specification) : Set(Vocabulary) =
+relevantDomainSpecifications(aSpecification)->collectNested(aDomainSpecification : DomainSpecification |
+ relevantVocabularies(aDomainSpecification)
+)->flatten()->asSet()
+/]
+
+[query public domainSpecificationImplicitVocabularyNamespaceConstantName(aDomainSpecification: DomainSpecification) : String =
+'NS_'.concat(aDomainSpecification.namespacePrefix.name.toUpperCase())
+/]
+
+[query public servicedResources(aRequiredAdaptor : RequiredAdaptor) : Set(Resource) =
+if (aRequiredAdaptor.oclIsTypeOf(GenericRequiredAdaptor)) then
+ servicedResourcesForGenericRequiredAdaptor(aRequiredAdaptor.oclAsType(GenericRequiredAdaptor))
+else
+ servicedResourcesForModelledRequiredAdaptor(aRequiredAdaptor.oclAsType(ModelledRequiredAdaptor))
+endif
+/]
+
+[query private servicedResourcesForGenericRequiredAdaptor(aGenericRequiredAdaptor : GenericRequiredAdaptor) : Set(Resource) =
+aGenericRequiredAdaptor.servicedResources
+/]
+
+[query private servicedResourcesForModelledRequiredAdaptor(aModelledRequiredAdaptor : ModelledRequiredAdaptor) : Set(Resource) =
+servicedResources(aModelledRequiredAdaptor.adaptorInterface)
+/]
+
+[query public relevantResources(aRequiredAdaptor : RequiredAdaptor) : Set(Resource) =
+servicedResources(aRequiredAdaptor)
+->union(servicedResources(aRequiredAdaptor)->collectNested(aResource : Resource | aResource.allRelatedResources())->flatten()->asSet())
+/]
+
+[query public relevantDomainSpecifications(aRequiredAdaptor : RequiredAdaptor) : Set(DomainSpecification) =
+relevantResources(aRequiredAdaptor)->collectNested(aResource : Resource |
+ definingDomainSpecification(aResource)
+ ->union(aResource.allProperties()->asSet()->collectNested(aResourceProperty : ResourceProperty | aResourceProperty.definingDomainSpecification()))
+)->flatten()->asSet()
+/]
+
+[query public servicedResources(aService : Service) : Set(Resource) =
+aService.creationFactories.resourceTypes->asSet()
+ ->union(aService.queryCapabilities.resourceTypes->asSet())
+ ->union(aService.basicCapabilities.resourceTypes->asSet())
+ ->union(aService.creationDialogs.resourceTypes->asSet())
+ ->union(aService.selectionDialogs.resourceTypes->asSet())
+/]
+
+[query public relevantResources(aService : Service) : Set(Resource) =
+(servicedResources(aService)
+->union(servicedResources(aService).allRelatedResources()))->flatten()->asSet()
+/]
+
+[query public relevantDomainSpecifications(aService : Service) : Set(DomainSpecification) =
+relevantResources(aService)->collectNested(aResource : Resource |
+ definingDomainSpecification(aResource)
+ ->union(aResource.allProperties()->asSet()->collectNested(aResourceProperty : ResourceProperty | aResourceProperty.definingDomainSpecification()))
+)->flatten()->asSet()
+->union(Set{aService.domainSpecification})
+/]
+
+[query public servicedResources(aServiceProvider : ServiceProvider) : Set(Resource) =
+aServiceProvider.services->collectNested(aService : Service | servicedResources(aService))->flatten()->asSet()
+/]
+
+[query public relevantResources(aServiceProvider : ServiceProvider) : Set(Resource) =
+aServiceProvider.services->collectNested(aService : Service | relevantResources(aService))->flatten()->asSet()
+/]
+
+[query public relevantDomainSpecifications(aServiceProvider : ServiceProvider) : Set(DomainSpecification) =
+aServiceProvider.services->collectNested(aService : Service | relevantDomainSpecifications(aService))->flatten()->asSet()
+/]
+
diff --git a/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/services/domainSpecificationServices.mtl b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/services/domainSpecificationServices.mtl
new file mode 100644
index 00000000..fdc9f336
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/services/domainSpecificationServices.mtl
@@ -0,0 +1,46 @@
+[comment encoding = UTF-8 /]
+[comment
+/*
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License 1.0
+ * which is available at http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Simple
+ */
+/]
+[module domainSpecificationServices('http://org.eclipse.lyo/oslc4j/adaptorInterface', 'http://org.eclipse.lyo/oslc4j/vocabulary')/]
+
+[import org::eclipse::lyo::oslc4j::codegenerator::python::services::services/]
+
+[query public definingDomainSpecification(aProperty: ResourceProperty) : DomainSpecification =
+aProperty.eContainer(DomainSpecification)
+/]
+
+[query public definingDomainSpecification(aResource: Resource) : DomainSpecification =
+aResource.eContainer(DomainSpecification)
+/]
+
+[query public pythonFullFolderNameForConstants(aDomainSpecification: DomainSpecification, anAdaptorInterface : AdaptorInterface, defaultFilesPath : String, defaultPackageName : String) : String =
+ pythonFilesBasePath(aDomainSpecification, anAdaptorInterface, defaultFilesPath)
+ .concatenatePaths(pythonPackageNameForConstants(aDomainSpecification, anAdaptorInterface, defaultPackageName).substituteAll('.', '/'))
+/]
+
+[query public pythonPackageNameForConstants(aDomainSpecification: DomainSpecification, anAdaptorInterface : AdaptorInterface, defaultPackageName : String) : String =
+pythonPackageName(aDomainSpecification, anAdaptorInterface, defaultPackageName)
+/]
+
+[query public pythonNameForConstants(aDomainSpecification: DomainSpecification) : String =
+aDomainSpecification.namespacePrefix.name.toLower().concat('_constants')
+/]
+
+[query public pythonFullFileNameForConstants(aDomainSpecification: DomainSpecification, anAdaptorInterface : AdaptorInterface, defaultFilesPath : String, defaultPackageName : String) : String =
+ pythonFullFolderNameForConstants(aDomainSpecification, anAdaptorInterface, defaultFilesPath, defaultPackageName)
+ .concatenatePaths(pythonNameForConstants(aDomainSpecification))
+ .concat('.py')
+/]
diff --git a/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/services/fileServices.mtl b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/services/fileServices.mtl
new file mode 100644
index 00000000..466c2076
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/services/fileServices.mtl
@@ -0,0 +1,25 @@
+[comment encoding = UTF-8 /]
+[comment
+/*
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License 1.0
+ * which is available at http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Simple
+ */
+/]
+[module fileServices('http://org.eclipse.lyo/oslc4j/adaptorInterface')/]
+
+[query public setTargetFolder(path : String): Boolean
+ = invoke('org.eclipse.lyo.oslc4j.codegenerator.python.services.FileServices', 'setTargetFolder(java.lang.String)', Sequence{path})
+/]
+
+[query public fileExists(filePath : String): Boolean
+ = invoke('org.eclipse.lyo.oslc4j.codegenerator.python.services.FileServices', 'fileExists(java.lang.String)', Sequence{filePath})
+/]
\ No newline at end of file
diff --git a/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/services/resourcePropertyServices.mtl b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/services/resourcePropertyServices.mtl
new file mode 100644
index 00000000..453a5e6c
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/services/resourcePropertyServices.mtl
@@ -0,0 +1,267 @@
+[comment encoding = UTF-8 /]
+[comment
+/*
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License 1.0
+ * which is available at http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Simple
+ */
+/]
+[module resourcePropertyServices('http://org.eclipse.lyo/oslc4j/adaptorInterface')/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::services::services/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::services::vocabularyServices/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::services::adaptorInterfaceServices/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::services::domainSpecificationServices/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::services::resourceServices/]
+
+[query public pythonName(aProperty: ResourceProperty, toUpperFirst : Boolean) : String =
+pythonString(aProperty.name, aProperty.definingDomainSpecification().namespacePrefix.name, toUpperFirst)
+/]
+
+[query public hasOSLCSupportedValueType(aProperty: ResourceProperty) : Boolean =
+not (Sequence{'URI'}->includes(aProperty.valueType.toString()))
+/]
+
+[query public resourcePropertyDefinitionNamespace(aResourceProperty: ResourceProperty) : String =
+(if (aResourceProperty.propertyDefinition.oclIsUndefined()) then
+ domainSpecificationImplicitVocabularyNamespaceConstantName(aResourceProperty.definingDomainSpecification())
+else
+ vocabularyNamespaceConstantName(aResourceProperty.propertyDefinition.definingVocabulary())
+endif)
+/]
+
+[query public resourcePropertyDefinitionLocalName(aResourceProperty: ResourceProperty) : String =
+(if (aResourceProperty.propertyDefinition.oclIsUndefined()) then
+ '"'.concat(aResourceProperty.name).concat('"')
+else
+ '"'.concat(aResourceProperty.propertyDefinition.name).concat('"')
+endif)
+/]
+
+
+[query public nameAnnotation(aProperty: ResourceProperty) : String =
+'@oslc_name('
+.concat(resourcePropertyDefinitionLocalName(aProperty))
+.concat(')')
+/]
+
+[query public propertyDefinitionAnnotation(aProperty: ResourceProperty, aResource: Resource, anAdaptorInterface: AdaptorInterface) : String =
+'@oslc_property_definition('
+.concat(resourcePropertyDefinitionNamespace(aProperty))
+.concat('[')
+.concat(resourcePropertyDefinitionLocalName(aProperty))
+.concat('])')
+/]
+
+[query public descriptionAnnotation(aProperty: ResourceProperty) : String =
+(if (not aProperty.description.oclIsUndefined()) then
+ '@oslc_description("'.concat(aProperty.description).concat('")')
+else
+ ''
+endif)
+/]
+
+[query public occursAnnotation(aProperty: ResourceProperty) : String =
+(if (not aProperty.occurs.oclIsUndefined()) then
+ if (aProperty.occurs = ResourcePropertyOccurs::exactlyOne) then
+ '@oslc_occurs(Occurs.EXACTLY_ONE)'
+ else
+ if (aProperty.occurs = ResourcePropertyOccurs::zeroOrOne) then
+ '@oslc_occurs(Occurs.ZERO_OR_ONE)'
+ else
+ if (aProperty.occurs = ResourcePropertyOccurs::zeroOrMany) then
+ '@oslc_occurs(Occurs.ZERO_OR_MANY)'
+ else
+ if (aProperty.occurs = ResourcePropertyOccurs::oneOrMany) then
+ '@oslc_occurs(Occurs.ONE_OR_MANY)'
+ else
+ ''
+ endif
+ endif
+ endif
+ endif
+else
+ ''
+endif)
+/]
+
+[query public valueTypeAnnotation(aProperty: ResourceProperty) : String =
+(if (not aProperty.valueType.oclIsUndefined()) then
+ if (hasOSLCSupportedValueType(aProperty)) then
+ '@oslc_value_type(ValueType.'.concat(aProperty.valueType.toString().toUpper()).concat(')')
+ else
+ ''
+ endif
+else
+ ''
+endif)
+/]
+
+[query public representationAnnotation(aProperty: ResourceProperty) : String =
+(if (not aProperty.representation.oclIsUndefined()) then
+ if (not aProperty.representation.toString().equalsIgnoreCase('n_a')) then
+ if (not aProperty.representation.toString().equalsIgnoreCase('either')) then
+ '@oslc_representation(Representation.'.concat(aProperty.representation.toString().toUpper()).concat(')')
+ else
+ ''
+ endif
+ else
+ ''
+ endif
+else
+ ''
+endif)
+/]
+
+[query public rdfCollectionTypeAnnotation(aProperty: ResourceProperty) : String =
+(if ((not aProperty.multiValueRepresentation.oclIsUndefined()) and (not aProperty.occurs.oclIsUndefined())) then
+ if (aProperty.occurs = ResourcePropertyOccurs::zeroOrMany or aProperty.occurs = ResourcePropertyOccurs::oneOrMany) then
+ if (aProperty.multiValueRepresentation = ResourcePropertyMultiValueRepresentation::rdfList) then
+ '@oslc_rdf_collection_type("List", "http://www.w3.org/1999/02/22-rdf-syntax-ns#")'
+ else
+ ''
+ endif
+ else
+ ''
+ endif
+else
+ ''
+endif)
+/]
+
+[query public rangeAnnotation(aProperty: ResourceProperty, aResource: Resource, anAdaptorInterface: AdaptorInterface) : String =
+(if (aProperty.range->size() > 0) then
+ '@oslc_range('
+ .concat(concatenate(aProperty.range->collect(aRange : Resource | aRange.definingDomainSpecification().domainSpecificationImplicitVocabularyNamespaceConstantName().concat('["').concat(if (aRange.describes.oclIsUndefined()) then aRange.name.substituteAll(' ', '') else aRange.describes.name.substituteAll(' ', '') endif).concat('"]')), ', '))
+ .concat(')')
+else
+ ''
+endif)
+/]
+
+[query public readOnlyAnnotation(aProperty: ResourceProperty) : String =
+(if (not aProperty.readOnly.oclIsUndefined()) then
+ '@oslc_read_only('.concat(if aProperty.readOnly then 'True' else 'False' endif).concat(')')
+else
+ ''
+endif)
+/]
+
+[query public titleAnnotation(aProperty: ResourceProperty) : String =
+(if (not aProperty.title.oclIsUndefined()) then
+ '@oslc_title("'.concat(aProperty.title).concat('")')
+else
+ ''
+endif)
+/]
+
+[query public isMemberPropertyAnnotation(aProperty: ResourceProperty) : String =
+if (aProperty.isMemberProperty.toString().equalsIgnoreCase('true')) then
+ '@oslc_member_property(True)'
+else
+ if (aProperty.isMemberProperty.toString().equalsIgnoreCase('false')) then
+ '@oslc_member_property(False)'
+ else
+ ''
+ endif
+endif
+/]
+
+[query public allowedValuesAnnotation(aProperty: ResourceProperty) : String =
+(if (aProperty.allowedValue->size() > 0) then
+ '@oslc_allowed_values(["'.concat(concatenate((aProperty.allowedValue)->asSequence(), '", "')).concat('"])')
+else
+ ''
+endif)
+/]
+
+[query public pythonAttributeTypeDeclaration(aProperty: ResourceProperty) : String =
+ (if (Sequence{'zeroOrMany', 'oneOrMany'}->includes(aProperty.occurs.toString())) then
+ 'Set['.concat(pythonAttributeBaseType(aProperty)).concat(']')
+ else
+ pythonAttributeBaseType(aProperty)
+ endif)
+/]
+
+[query public pythonAttributeInitialConstruction(aProperty: ResourceProperty) : String =
+ (if (Sequence{'zeroOrMany', 'oneOrMany'}->includes(aProperty.occurs.toString())) then
+ 'set()'
+ else
+ 'None'
+ endif)
+/]
+
+[query public pythonAttributeBaseType(aProperty: ResourceProperty) : String =
+ (if (aProperty.valueType.toString() = 'String') then
+ 'str'
+ else
+ if (aProperty.valueType.toString() = 'XMLLiteral') then
+ 'str'
+ else
+ if(aProperty.valueType.toString() = 'DateTime') then
+ 'datetime'
+ else
+ if(aProperty.valueType.toString() = 'URI') then
+ 'str'
+ else
+ if(aProperty.valueType.toString() = 'Boolean') then
+ 'bool'
+ else
+ if(aProperty.valueType.toString() = 'Double') then
+ 'float'
+ else
+ if(aProperty.valueType.toString() = 'Float') then
+ 'float'
+ else
+ if(aProperty.valueType.toString() = 'Integer') then
+ 'int'
+ else
+ if(aProperty.valueType.toString() = 'Resource') then
+ if ((not aProperty.representation.oclIsUndefined()) and (aProperty.representation.toString().equalsIgnoreCase('inline'))) then
+ if (aProperty.range->size() = 1) then
+ pythonClassName(aProperty.range->first())
+ else
+ 'Link'
+ endif
+ else
+ 'Link'
+ endif
+ else
+ if(aProperty.valueType.toString() = 'LocalResource') then
+ if (aProperty.range->size() = 1) then
+ pythonClassName(aProperty.range->first())
+ else
+ 'Link'
+ endif
+ else
+ ''
+ endif
+ endif
+ endif
+ endif
+ endif
+ endif
+ endif
+ endif
+ endif
+ endif)
+/]
+
+[query public pythonAttributeName(aProperty: ResourceProperty, aResource: Resource) : String =
+ pythonAttributeName(aProperty)
+/]
+
+[query public pythonAttributeGetterMethodName(aProperty: ResourceProperty, aResource: Resource) : String =
+ pythonAttributeName(aProperty, aResource)
+/]
+
+[query public pythonAttributeSetterMethodName(aProperty: ResourceProperty, aResource: Resource) : String =
+ pythonAttributeName(aProperty, aResource)
+/]
diff --git a/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/services/resourceServices.mtl b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/services/resourceServices.mtl
new file mode 100644
index 00000000..59d29c27
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/services/resourceServices.mtl
@@ -0,0 +1,198 @@
+[comment encoding = UTF-8 /]
+[comment
+/*
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License 1.0
+ * which is available at http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Simple
+ */
+/]
+[module resourceServices('http://org.eclipse.lyo/oslc4j/adaptorInterface', 'http://org.eclipse.lyo/oslc4j/vocabulary')/]
+
+[import org::eclipse::lyo::oslc4j::codegenerator::python::services::services/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::services::domainSpecificationServices/]
+
+[query public generate(aResource: Resource) : Boolean =
+ not aResource.definingDomainSpecification().doNotGenerate()
+/]
+
+[query public directParentResource(aResource: Resource) : Resource =
+ (if (aResource.extends->notEmpty()) then
+ aResource.extends->first()
+ else
+ null
+ endif)
+/]
+
+[query public parentResources(aResource: Resource) : Set(Resource) =
+ (if (directParentResource(aResource)->notEmpty()) then
+ directParentResource(aResource)->union(parentResources(directParentResource(aResource)))
+ else
+ Set{}
+ endif)
+/]
+
+[query public allExtendingResources(aResource: Resource) : OrderedSet(Resource) =
+ aResource.extends
+ ->union(
+ aResource.extends->collectNested(r:Resource | allExtendingResources(r))->flatten()->asOrderedSet()
+ )
+ ->asOrderedSet()
+/]
+
+[comment The interfaceResources of resource A, are its directInterfaceResources; plus for each such directInterfaceResource DIR, ALL the extendingResources of DIR.
+However, if an extendingResource of DIR is also a ParentResource of A, then exclude this resource from the interface set.
+It is a problem if a resource X is defined to be both an interface of A, as well as one of its (distant) parents. Since, the resource shape would end up defining each of X's properties twice/]
+[query public interfaceResources(aResource: Resource) : OrderedSet(Resource) =
+ ((directInterfaceResources(aResource)
+ ->union(
+ directInterfaceResources(aResource)->collectNested(r:Resource | allExtendingResources(r))->flatten()->asOrderedSet()
+ )
+ ->asOrderedSet())
+ - parentResources(aResource))
+ ->asOrderedSet()
+/]
+
+[query private directInterfaceResources(aResource: Resource) : OrderedSet(Resource) =
+ (if (aResource.extends->size() > 1) then
+ aResource.extends->subOrderedSet(2, aResource.extends->size())
+ else
+ OrderedSet{}
+ endif)
+
+/]
+
+[query public directlyRelatedResources(aResource: Resource) : Set(Resource) =
+ (aResource.resourceProperties->collect(p : ResourceProperty | p.range))->flatten()->asSet()
+ ->union(
+ aResource.extends
+ )->flatten()->asSet()
+/]
+
+[comment allRelatedResources seems to hang for long & complicated hierarchy of resources.
+As an intermediate solution, the depth parameter is introduced to allow the recursive query to stop once a certain limit is reached /]
+[query private allRelatedResources(aResource: Resource, alreadyAnalysed : Set(Resource), depth : Integer) : Set(Resource) =
+let drr : Set(Resource) = directlyRelatedResources(aResource),
+ newAlreadyAnalysed : Set(Resource) = (Set{aResource}->union(drr))->union(alreadyAnalysed),
+ toAnalyse : Set(Resource) = drr - alreadyAnalysed in
+
+ (if (depth > 20) then
+ drr - alreadyAnalysed
+ else
+ toAnalyse->collect(r : Resource |
+ allRelatedResources(r, newAlreadyAnalysed, depth+1)
+ ->union(directlyRelatedResources(r))
+ ->union(Set{r})
+ )->flatten()->asSet()
+ endif)
+/]
+
+[comment allRelatedResources seems to hang for long & complicated hierarchy of resources.
+As an intermediate solution, the depth parameter is introduced to allow the recursive query to stop once a certain limit is reached.
+After that, we look at what related resources might be potentially missing, and then re-start the query for the remaining resources.
+This is not a complete solution, but seems to be working for the Autosar 800+ resources.
+It is not clear why the recursion is ending up in an endless loop otherwise. /]
+[query public allRelatedResources(aResource: Resource) : Set(Resource) =
+let arr : Set(Resource) = allRelatedResources(aResource, Set{}, 1),
+ leftOut : Set(Resource) = arr->collect(r : Resource | directlyRelatedResources(r) - arr)->flatten()->asSet()
+in
+ arr
+ ->union(leftOut)
+ ->union(leftOut->collect(r : Resource | allRelatedResources(r, arr->union(Set{r}), 1))->flatten()->asSet())
+/]
+
+[query public allProperties(aResource: Resource) : Sequence(ResourceProperty) =
+((aResource.resourceProperties->asSequence())
+ ->union(inheritedProperties(aResource))
+ ->union(interfaceProperties(aResource))
+)
+/]
+
+[query public inheritedProperties(aResource: Resource) : Sequence(ResourceProperty) =
+ (if (not aResource.directParentResource().oclIsUndefined()) then
+ (aResource.directParentResource().resourceProperties->asSequence())->union(inheritedProperties(aResource.directParentResource()))
+ else
+ Sequence{}
+ endif)
+/]
+
+[query public interfaceProperties(aResource: Resource) : Sequence(ResourceProperty) =
+ aResource.interfaceResources().resourceProperties
+/]
+
+
+[query public pythonName(aResource: Resource) : String =
+pythonString(aResource.name, aResource.definingDomainSpecification().namespacePrefix.name, true)
+/]
+
+[query public pythonClassFullFolderName(aResource: Resource, anAdaptorInterface : AdaptorInterface, defaultFilesPath : String, defaultPackageName : String) : String =
+ pythonFilesBasePath(aResource.definingDomainSpecification(), anAdaptorInterface, defaultFilesPath)
+ .concatenatePaths(pythonClassPackageName(aResource, anAdaptorInterface, defaultPackageName).substituteAll('.', '/'))
+/]
+
+[query public pythonClassPackageName(aResource: Resource, anAdaptorInterface : AdaptorInterface, defaultPackageName : String) : String =
+pythonPackageName(aResource.definingDomainSpecification(), anAdaptorInterface, defaultPackageName)
+/]
+
+[query public pythonClassName(aResource: Resource) : String =
+pythonName(aResource)
+/]
+
+[query public pythonClassFullFileName(aResource: Resource, anAdaptorInterface : AdaptorInterface, defaultFilesPath : String, defaultPackageName : String) : String =
+ pythonClassFullFolderName(aResource, anAdaptorInterface, defaultFilesPath, defaultPackageName)
+ .concatenatePaths(pythonClassName(aResource))
+ .concat('.py')
+/]
+
+[query public pythonNameAnnotation(aResource: Resource) : String =
+'@oslc_name("'
+.concat(if (aResource.describes.oclIsUndefined()) then aResource.name.substituteAll(' ', '') else aResource.describes.name.substituteAll(' ', '') endif)
+.concat('")')
+/]
+
+[query public pythonNamespaceAnnotation(aResource: Resource) : String =
+'@oslc_namespace('
+.concat('NS_'.concat(aResource.definingDomainSpecification().namespacePrefix.name.toUpperCase()))
+.concat(')')
+/]
+
+[query public pythonResourceShapeAnnotation(aResource: Resource) : String =
+'@oslc_resource_shape(describes='
+.concat('NS_'.concat(aResource.definingDomainSpecification().namespacePrefix.name.toUpperCase()))
+.concat('["')
+.concat(if (aResource.describes.oclIsUndefined()) then aResource.name.substituteAll(' ', '') else aResource.describes.name.substituteAll(' ', '') endif)
+.concat('"], title="')
+.concat(if (aResource.title.oclIsUndefined()) then aResource.name.concat(' Shape') else aResource.title endif)
+.concat('")')
+/]
+
+[query public pythonAttributeName(aProperty: ResourceProperty) : String =
+ pythonAttributeNameString(aProperty.name)
+/]
+
+[query private pythonAttributeNameString(aString : String) : String =
+ aString.replaceAll('([a-z])([A-Z]+)', '$1_$2').toLower()
+/]
+
+[query public pythonAttributeName(aProperty: ResourceProperty, aResource : Resource) : String =
+ pythonAttributeName(aProperty)
+/]
+
+[query public hasDateTimeProperty(aResource: Resource) : Boolean =
+ allProperties(aResource)->exists(p | p.valueType.toString() = 'DateTime')
+/]
+
+[query public hasSetProperty(aResource: Resource) : Boolean =
+ allProperties(aResource)->exists(p | Sequence{'zeroOrMany', 'oneOrMany'}->includes(p.occurs.toString()))
+/]
+
+[query public hasLinkProperty(aResource: Resource) : Boolean =
+ allProperties(aResource)->exists(p | Sequence{'Resource', 'LocalResource'}->includes(p.valueType.toString()))
+/]
diff --git a/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/services/services.mtl b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/services/services.mtl
new file mode 100644
index 00000000..05257b12
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/services/services.mtl
@@ -0,0 +1,314 @@
+[comment encoding = UTF-8 /]
+[comment
+/*
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License 1.0
+ * which is available at http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Simple
+ */
+/]
+[module services('http://org.eclipse.lyo/oslc4j/adaptorInterface', 'http://org.eclipse.lyo/oslc4j/vocabulary', 'http://www.eclipse.org/emf/2002/Ecore')/]
+
+[query private pythonKeywords(traceabilityContext : OclAny) : Set(String) =
+Set{'False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield'}
+/]
+
+[query private isPythonSpecialWord(aString : String) : Boolean =
+pythonKeywords(aString)->includes(aString)
+/]
+
+[query public pythonBasePackageName(anAdaptorInterface : AdaptorInterface) : String =
+anAdaptorInterface.pythonBasePackageName('resources')
+/]
+
+[query public pythonBasePackageName(anAdaptorInterface : AdaptorInterface, default : String) : String =
+(if anAdaptorInterface.configuration.oclIsUndefined()._or(anAdaptorInterface.configuration.generalConfiguration.oclIsUndefined()) then
+ (if anAdaptorInterface.javaClassBaseNamespace.isNullOrEmpty() then
+ default
+ else
+ anAdaptorInterface.javaClassBaseNamespace
+ endif)
+else
+ anAdaptorInterface.configuration.generalConfiguration.javaBasePackageName
+endif)
+/]
+
+[query public pythonPackageName(aSpecification: Specification, anAdaptorInterface : AdaptorInterface, default : String) : String =
+(if (aSpecification.configuration.oclIsUndefined())._or(aSpecification.configuration.generalConfiguration.javaBasePackageName.isNullOrEmpty()) then
+ (if (anAdaptorInterface.oclIsUndefined()) then
+ default
+ else
+ anAdaptorInterface.pythonBasePackageName(default).concat('.resources')
+ endif)
+else
+ aSpecification.configuration.generalConfiguration.javaBasePackageName
+endif).substituteAll('.', '_')
+/]
+
+[query public pythonPackageName(vocabularies: Vocabularies, anAdaptorInterface : AdaptorInterface, default : String) : String =
+(if (vocabularies.configuration.oclIsUndefined())._or(vocabularies.configuration.generalConfiguration.javaBasePackageName.isNullOrEmpty()) then
+ (if (anAdaptorInterface.oclIsUndefined()) then
+ default
+ else
+ anAdaptorInterface.pythonBasePackageName(default).concat('.resources')
+ endif)
+else
+ vocabularies.configuration.generalConfiguration.javaBasePackageName
+endif).substituteAll('.', '_')
+/]
+
+[query public pythonPackageName(aDomainSpecification: DomainSpecification, anAdaptorInterface : AdaptorInterface, default : String) : String =
+(if (aDomainSpecification.configuration.oclIsUndefined())._or(aDomainSpecification.configuration.generalConfiguration.javaBasePackageName.isNullOrEmpty()) then
+ aDomainSpecification.eContainer(Specification).pythonPackageName(anAdaptorInterface, default)
+else
+ aDomainSpecification.configuration.generalConfiguration.javaBasePackageName
+endif).substituteAll('.', '_')
+/]
+
+[query public pythonPackageName(aVocabulary: Vocabulary, anAdaptorInterface : AdaptorInterface, default : String) : String =
+(if (aVocabulary.configuration.oclIsUndefined())._or(aVocabulary.configuration.generalConfiguration.javaBasePackageName.isNullOrEmpty()) then
+ aVocabulary.eContainer(Vocabularies).pythonPackageName(anAdaptorInterface, default)
+else
+ aVocabulary.configuration.generalConfiguration.javaBasePackageName
+endif).substituteAll('.', '_')
+/]
+
+[query public filesBasePath(anAdaptorInterface : AdaptorInterface) : String =
+anAdaptorInterface.filesBasePath('.')
+/]
+
+[query public filesBasePath(anAdaptorInterface : AdaptorInterface, default : String) : String =
+(if anAdaptorInterface.configuration.oclIsUndefined()._or(anAdaptorInterface.configuration.generalConfiguration.oclIsUndefined()) then
+ (if anAdaptorInterface.javaFilesBasePath.isNullOrEmpty() then
+ default
+ else
+ anAdaptorInterface.javaFilesBasePath.substitute('/src/main/python', '')
+ endif)
+else
+ anAdaptorInterface.configuration.generalConfiguration.filesBasePath
+endif)
+/]
+
+[query public filesBasePath(aSpecification: Specification, anAdaptorInterface : AdaptorInterface, default : String) : String =
+(if (aSpecification.configuration.oclIsUndefined())._or(aSpecification.configuration.generalConfiguration.filesBasePath.isNullOrEmpty()) then
+ (if (anAdaptorInterface.oclIsUndefined()) then
+ default
+ else
+ anAdaptorInterface.filesBasePath(default)
+ endif)
+else
+ aSpecification.configuration.generalConfiguration.filesBasePath
+endif)
+/]
+
+[query public filesBasePath(vocabularies: Vocabularies, anAdaptorInterface : AdaptorInterface, default : String) : String =
+(if (vocabularies.configuration.oclIsUndefined())._or(vocabularies.configuration.generalConfiguration.filesBasePath.isNullOrEmpty()) then
+ (if (anAdaptorInterface.oclIsUndefined()) then
+ default
+ else
+ anAdaptorInterface.filesBasePath(default)
+ endif)
+else
+ vocabularies.configuration.generalConfiguration.filesBasePath
+endif)
+/]
+
+[query public filesBasePath(aDomainSpecification: DomainSpecification, anAdaptorInterface : AdaptorInterface, default : String) : String =
+(if (aDomainSpecification.configuration.oclIsUndefined())._or(aDomainSpecification.configuration.generalConfiguration.filesBasePath.isNullOrEmpty()) then
+ aDomainSpecification.eContainer(Specification).filesBasePath(anAdaptorInterface, default)
+else
+ aDomainSpecification.configuration.generalConfiguration.filesBasePath
+endif)
+/]
+
+[query public filesBasePath(aVocabulary: Vocabulary, anAdaptorInterface : AdaptorInterface, default : String) : String =
+(if (aVocabulary.configuration.oclIsUndefined())._or(aVocabulary.configuration.generalConfiguration.filesBasePath.isNullOrEmpty()) then
+ aVocabulary.eContainer(Vocabularies).filesBasePath(anAdaptorInterface, default)
+else
+ aVocabulary.configuration.generalConfiguration.filesBasePath
+endif)
+/]
+
+[query private pythonFilesRelativePath(traceabilityContext : OclAny) : String =
+'/src'
+/]
+
+[query public pythonFilesBasePath(anAdaptorInterface : AdaptorInterface) : String =
+anAdaptorInterface.filesBasePath().concatenatePaths(pythonFilesRelativePath())
+/]
+
+[query public pythonFilesBasePath(anAdaptorInterface : AdaptorInterface, default : String) : String =
+anAdaptorInterface.filesBasePath(default).concatenatePaths(pythonFilesRelativePath())
+/]
+
+[query public pythonFilesBasePath(aSpecification: Specification, anAdaptorInterface : AdaptorInterface, default : String) : String =
+aSpecification.filesBasePath(anAdaptorInterface, default).concatenatePaths(pythonFilesRelativePath())
+/]
+
+[query public pythonFilesBasePath(vocabularies: Vocabularies, anAdaptorInterface : AdaptorInterface, default : String) : String =
+vocabularies.filesBasePath(anAdaptorInterface, default).concatenatePaths(pythonFilesRelativePath())
+/]
+
+[query public pythonFilesBasePath(aDomainSpecification: DomainSpecification, anAdaptorInterface : AdaptorInterface, default : String) : String =
+aDomainSpecification.filesBasePath(anAdaptorInterface, default).concatenatePaths(pythonFilesRelativePath())
+/]
+
+[query public pythonFilesBasePath(aVocabulary: Vocabulary, anAdaptorInterface : AdaptorInterface, default : String) : String =
+aVocabulary.filesBasePath(anAdaptorInterface, default).concatenatePaths(pythonFilesRelativePath())
+/]
+
+[query public isFromImportedModels(anAdaptorInterface : AdaptorInterface, obj : EObject) : Boolean =
+ not (anAdaptorInterface.eResource() = obj.eResource())
+/]
+
+[query public isFromImportedModels(aSpecification: Specification, obj : EObject) : Boolean =
+ not (aSpecification.eResource() = obj.eResource())
+/]
+
+[comment unlike other "do not generate" flags, doNotGenerateFromImportedModels is not recursive.
+We only read the top level "doNotGenerateFromImportedModels" and decide whether objects from any imported model (direct or indirect) will be generated./]
+[query public generateIfFromImportedModels(anAdaptorInterface : AdaptorInterface, obj : EObject) : Boolean =
+ not anAdaptorInterface.doNotGenerateFromImportedModels()
+ or (not anAdaptorInterface.isFromImportedModels(obj))
+/]
+
+[query public generateIfFromImportedModels(aSpecification: Specification, obj : EObject) : Boolean =
+ not aSpecification.doNotGenerateFromImportedModels()
+ or (not aSpecification.isFromImportedModels(obj))
+/]
+
+[query public doNotGenerateFromImportedModels(anAdaptorInterface : AdaptorInterface) : Boolean =
+(if (anAdaptorInterface.configuration.oclIsUndefined())._or(anAdaptorInterface.configuration.generalConfiguration.doNotGenerateFromImportedModels.oclIsUndefined()) then
+ false
+else
+ anAdaptorInterface.configuration.generalConfiguration.doNotGenerateFromImportedModels
+endif)
+/]
+
+[query public doNotGenerateFromImportedModels(aSpecification: Specification) : Boolean =
+(if (aSpecification.configuration.oclIsUndefined())._or(aSpecification.configuration.generalConfiguration.doNotGenerateFromImportedModels.oclIsUndefined()) then
+ false
+else
+ aSpecification.configuration.generalConfiguration.doNotGenerateFromImportedModels
+endif)
+/]
+
+[query public doNotGenerate(aSpecification: Specification) : Boolean =
+(if (aSpecification.configuration.oclIsUndefined())._or(aSpecification.configuration.generalConfiguration.doNotGenerate.oclIsUndefined()) then
+ false
+else
+ aSpecification.configuration.generalConfiguration.doNotGenerate
+endif)
+/]
+
+[query public doNotGenerate(vocabularies: Vocabularies) : Boolean =
+(if (vocabularies.configuration.oclIsUndefined())._or(vocabularies.configuration.generalConfiguration.doNotGenerate.oclIsUndefined()) then
+ false
+else
+ vocabularies.configuration.generalConfiguration.doNotGenerate
+endif)
+/]
+
+[query public doNotGenerate(aDomainSpecification: DomainSpecification) : Boolean =
+(if (aDomainSpecification.configuration.oclIsUndefined())._or(aDomainSpecification.configuration.generalConfiguration.doNotGenerate.oclIsUndefined()) then
+ aDomainSpecification.eContainer(Specification).doNotGenerate()
+else
+ aDomainSpecification.configuration.generalConfiguration.doNotGenerate
+endif)
+/]
+
+[query public doNotGenerate(aVocabulary: Vocabulary) : Boolean =
+(if (aVocabulary.configuration.oclIsUndefined())._or(aVocabulary.configuration.generalConfiguration.doNotGenerate.oclIsUndefined()) then
+ aVocabulary.eContainer(Vocabularies).doNotGenerate()
+else
+ aVocabulary.configuration.generalConfiguration.doNotGenerate
+endif)
+/]
+
+[query private stripURISegmentEnd(URISegment : String) : String =
+(if (URISegment.size() = 0) then
+ URISegment
+else
+ (if (URISegment.size() = 1) then
+ (if (URISegment.endsWith('/')) then '' else URISegment endif)
+ else
+ URISegment.substring(1, URISegment.size()-(if (URISegment.endsWith('/')) then 1 else 0 endif))
+ endif)
+endif)
+/]
+
+[query private stripURISegmentStart(URISegment : String) : String =
+(if (URISegment.size() = 0) then
+ URISegment
+else
+ (if (URISegment.size() = 1) then
+ (if (URISegment.startsWith('/')) then '' else URISegment endif)
+ else
+ URISegment.substring((if (URISegment.startsWith('/')) then 2 else 1 endif), URISegment.size())
+ endif)
+endif)
+/]
+
+[comment if the leftSegment is empty or "/", then we take the rightSegment as is.
+We don't strip the rightSegment, because we want to keep the starting / - if it exists. /]
+[query public concatenatePaths (leftSegment : String, rightSegment : String) : String =
+(if (stripURISegmentEnd(leftSegment).size() = 0) then
+ rightSegment
+else
+ (if (stripURISegmentStart(rightSegment).size() = 0) then
+ leftSegment
+ else
+ stripURISegmentEnd(leftSegment).concat('/').concat(stripURISegmentStart(rightSegment))
+ endif)
+endif)
+/]
+
+[query public pythonConstantString (aString : String) : String =
+concatenate(
+ aString.replaceAll('\\W+', '_').tokenize('_')->sep('_').oclAsType(String)
+).toUpperCase()
+/]
+
+[query private pythonString (aString : String) : String =
+concatenate(
+ aString.replaceAll('\\W+', ' ').tokenize(' ')->collect(s : String | s.toUpperFirst())
+)
+/]
+
+[query public pythonString (aString : String, prefixIfNecessary : String, toUpperFirst : Boolean) : String =
+let base : String = (if (isPythonSpecialWord(aString)) then prefixIfNecessary.concat(pythonString(aString).toUpperFirst()) else pythonString(aString) endif)
+in
+if (toUpperFirst) then base.toUpperFirst() else base.toLowerFirst() endif
+/]
+[query public concatenate (aStringSequence : Sequence(String), separatorString : String) : String =
+ concatenate(aStringSequence->sep(separatorString).oclAsType(String))
+/]
+
+[query public concatenate (aStringSequence : Sequence(String)) : String =
+(if (aStringSequence->size() = 0) then
+ ''
+else
+ (if (aStringSequence->size() = 1) then
+ aStringSequence->at(1)
+ else
+ (if (aStringSequence->size() = 2) then
+ aStringSequence->at(1).concat(aStringSequence->at(2))
+ else
+ aStringSequence->at(1).concat(aStringSequence->at(2)).concat(concatenate(aStringSequence->subSequence(3, aStringSequence->size())))
+ endif)
+ endif)
+endif)
+/]
+
+[query public isNullOrEmpty (aString : String) : Boolean =
+(aString.oclIsUndefined())._or(aString.trim().equalsIgnoreCase(''))
+/]
+
+
diff --git a/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/services/vocabularyServices.mtl b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/services/vocabularyServices.mtl
new file mode 100644
index 00000000..ca39635f
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/services/vocabularyServices.mtl
@@ -0,0 +1,46 @@
+[comment encoding = UTF-8 /]
+[comment
+/*
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License 1.0
+ * which is available at http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Simple
+ */
+/]
+[module vocabularyServices('http://org.eclipse.lyo/oslc4j/adaptorInterface', 'http://org.eclipse.lyo/oslc4j/vocabulary')/]
+
+[import org::eclipse::lyo::oslc4j::codegenerator::python::services::services/]
+
+[query public definingVocabulary(aProperty: Property) : Vocabulary =
+aProperty.eContainer(Vocabulary)
+/]
+
+[query public definingVocabulary(aClass: Class) : Vocabulary =
+aClass.eContainer(Vocabulary)
+/]
+
+[query public pythonPackageNameForConstants(aVocabulary: Vocabulary, anAdaptorInterface : AdaptorInterface, defaultPackageName : String) : String =
+pythonPackageName(aVocabulary, anAdaptorInterface, defaultPackageName)
+/]
+
+[query public pythonNameForConstants(aVocabulary: Vocabulary) : String =
+aVocabulary.preferredNamespacePrefix.toLower().concat('_vocabulary_constants')
+/]
+
+[query public pythonFullFileNameForConstants(aVocabulary: Vocabulary, anAdaptorInterface : AdaptorInterface, defaultFilesPath : String, defaultPackageName : String) : String =
+ pythonFilesBasePath(aVocabulary, anAdaptorInterface, defaultFilesPath)
+ .concatenatePaths(pythonPackageNameForConstants(aVocabulary, anAdaptorInterface, defaultPackageName).substituteAll('.', '/'))
+ .concatenatePaths(pythonNameForConstants(aVocabulary))
+ .concat('.py')
+/]
+
+[query public vocabularyNamespaceConstantName(aVocabulary : Vocabulary) : String =
+'NS_'.concat(aVocabulary.preferredNamespacePrefix.toUpperCase()).concat('_VOCABULARY')
+/]
\ No newline at end of file
diff --git a/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/staticFiles/generateEDLV10HTML.mtl b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/staticFiles/generateEDLV10HTML.mtl
new file mode 100644
index 00000000..8b65109f
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/staticFiles/generateEDLV10HTML.mtl
@@ -0,0 +1,67 @@
+[comment encoding = UTF-8 /]
+[module generateEDLV10HTML('http://org.eclipse.lyo/oslc4j/adaptorInterface')/]
+
+[template public generateEDLV10HTML(traceabilityContext : OclAny)]
+[file ('license/edl-v10.html', false, 'UTF-8')]
+
+
+
+
+
+
+Eclipse Distribution License - Version 1.0
+
+
+
+
+
+
+Eclipse Distribution License - v 1.0
+
+Copyright (c) 2007, Eclipse Foundation, Inc. and its licensors.
+
+All rights reserved.
+Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
- Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+- Neither the name of the Eclipse Foundation, Inc. nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+
+
+
+[/file]
+[/template]
+
diff --git a/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/staticFiles/generateEPLV10HTML.mtl b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/staticFiles/generateEPLV10HTML.mtl
new file mode 100644
index 00000000..a3b8a5e3
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/staticFiles/generateEPLV10HTML.mtl
@@ -0,0 +1,268 @@
+[comment encoding = UTF-8 /]
+[module generateEPLV10HTML('http://org.eclipse.lyo/oslc4j/adaptorInterface')/]
+
+[template public generateEPLV10HTML(traceabilityContext : OclAny)]
+[file ('license/epl-v10.html', false, 'UTF-8')]
+
+
+
+
+Eclipse Public License - Version 1.0
+
+
+
+
+
+
+Eclipse Public License - v 1.0
+
+THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
+PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR
+DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS
+AGREEMENT.
+
+1. DEFINITIONS
+
+"Contribution" means:
+
+a) in the case of the initial Contributor, the initial
+code and documentation distributed under this Agreement, and
+b) in the case of each subsequent Contributor:
+i) changes to the Program, and
+ii) additions to the Program;
+where such changes and/or additions to the Program
+originate from and are distributed by that particular Contributor. A
+Contribution 'originates' from a Contributor if it was added to the
+Program by such Contributor itself or anyone acting on such
+Contributor's behalf. Contributions do not include additions to the
+Program which: (i) are separate modules of software distributed in
+conjunction with the Program under their own license agreement, and (ii)
+are not derivative works of the Program.
+
+"Contributor" means any person or entity that distributes
+the Program.
+
+"Licensed Patents" mean patent claims licensable by a
+Contributor which are necessarily infringed by the use or sale of its
+Contribution alone or when combined with the Program.
+
+"Program" means the Contributions distributed in accordance
+with this Agreement.
+
+"Recipient" means anyone who receives the Program under
+this Agreement, including all Contributors.
+
+2. GRANT OF RIGHTS
+
+a) Subject to the terms of this Agreement, each
+Contributor hereby grants Recipient a non-exclusive, worldwide,
+royalty-free copyright license to reproduce, prepare derivative works
+of, publicly display, publicly perform, distribute and sublicense the
+Contribution of such Contributor, if any, and such derivative works, in
+source code and object code form.
+
+b) Subject to the terms of this Agreement, each
+Contributor hereby grants Recipient a non-exclusive, worldwide,
+royalty-free patent license under Licensed Patents to make, use, sell,
+offer to sell, import and otherwise transfer the Contribution of such
+Contributor, if any, in source code and object code form. This patent
+license shall apply to the combination of the Contribution and the
+Program if, at the time the Contribution is added by the Contributor,
+such addition of the Contribution causes such combination to be covered
+by the Licensed Patents. The patent license shall not apply to any other
+combinations which include the Contribution. No hardware per se is
+licensed hereunder.
+
+c) Recipient understands that although each Contributor
+grants the licenses to its Contributions set forth herein, no assurances
+are provided by any Contributor that the Program does not infringe the
+patent or other intellectual property rights of any other entity. Each
+Contributor disclaims any liability to Recipient for claims brought by
+any other entity based on infringement of intellectual property rights
+or otherwise. As a condition to exercising the rights and licenses
+granted hereunder, each Recipient hereby assumes sole responsibility to
+secure any other intellectual property rights needed, if any. For
+example, if a third party patent license is required to allow Recipient
+to distribute the Program, it is Recipient's responsibility to acquire
+that license before distributing the Program.
+
+d) Each Contributor represents that to its knowledge it
+has sufficient copyright rights in its Contribution, if any, to grant
+the copyright license set forth in this Agreement.
+
+3. REQUIREMENTS
+
+A Contributor may choose to distribute the Program in object code
+form under its own license agreement, provided that:
+
+a) it complies with the terms and conditions of this
+Agreement; and
+
+b) its license agreement:
+
+i) effectively disclaims on behalf of all Contributors
+all warranties and conditions, express and implied, including warranties
+or conditions of title and non-infringement, and implied warranties or
+conditions of merchantability and fitness for a particular purpose;
+
+ii) effectively excludes on behalf of all Contributors
+all liability for damages, including direct, indirect, special,
+incidental and consequential damages, such as lost profits;
+
+iii) states that any provisions which differ from this
+Agreement are offered by that Contributor alone and not by any other
+party; and
+
+iv) states that source code for the Program is available
+from such Contributor, and informs licensees how to obtain it in a
+reasonable manner on or through a medium customarily used for software
+exchange.
+
+When the Program is made available in source code form:
+
+a) it must be made available under this Agreement; and
+
+b) a copy of this Agreement must be included with each
+copy of the Program.
+
+Contributors may not remove or alter any copyright notices contained
+within the Program.
+
+Each Contributor must identify itself as the originator of its
+Contribution, if any, in a manner that reasonably allows subsequent
+Recipients to identify the originator of the Contribution.
+
+4. COMMERCIAL DISTRIBUTION
+
+Commercial distributors of software may accept certain
+responsibilities with respect to end users, business partners and the
+like. While this license is intended to facilitate the commercial use of
+the Program, the Contributor who includes the Program in a commercial
+product offering should do so in a manner which does not create
+potential liability for other Contributors. Therefore, if a Contributor
+includes the Program in a commercial product offering, such Contributor
+("Commercial Contributor") hereby agrees to defend and
+indemnify every other Contributor ("Indemnified Contributor")
+against any losses, damages and costs (collectively "Losses")
+arising from claims, lawsuits and other legal actions brought by a third
+party against the Indemnified Contributor to the extent caused by the
+acts or omissions of such Commercial Contributor in connection with its
+distribution of the Program in a commercial product offering. The
+obligations in this section do not apply to any claims or Losses
+relating to any actual or alleged intellectual property infringement. In
+order to qualify, an Indemnified Contributor must: a) promptly notify
+the Commercial Contributor in writing of such claim, and b) allow the
+Commercial Contributor to control, and cooperate with the Commercial
+Contributor in, the defense and any related settlement negotiations. The
+Indemnified Contributor may participate in any such claim at its own
+expense.
+
+For example, a Contributor might include the Program in a commercial
+product offering, Product X. That Contributor is then a Commercial
+Contributor. If that Commercial Contributor then makes performance
+claims, or offers warranties related to Product X, those performance
+claims and warranties are such Commercial Contributor's responsibility
+alone. Under this section, the Commercial Contributor would have to
+defend claims against the other Contributors related to those
+performance claims and warranties, and if a court requires any other
+Contributor to pay any damages as a result, the Commercial Contributor
+must pay those damages.
+
+5. NO WARRANTY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
+PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
+OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION,
+ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
+OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
+responsible for determining the appropriateness of using and
+distributing the Program and assumes all risks associated with its
+exercise of rights under this Agreement , including but not limited to
+the risks and costs of program errors, compliance with applicable laws,
+damage to or loss of data, programs or equipment, and unavailability or
+interruption of operations.
+
+6. DISCLAIMER OF LIABILITY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT
+NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
+WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
+DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+7. GENERAL
+
+If any provision of this Agreement is invalid or unenforceable under
+applicable law, it shall not affect the validity or enforceability of
+the remainder of the terms of this Agreement, and without further action
+by the parties hereto, such provision shall be reformed to the minimum
+extent necessary to make such provision valid and enforceable.
+
+If Recipient institutes patent litigation against any entity
+(including a cross-claim or counterclaim in a lawsuit) alleging that the
+Program itself (excluding combinations of the Program with other
+software or hardware) infringes such Recipient's patent(s), then such
+Recipient's rights granted under Section 2(b) shall terminate as of the
+date such litigation is filed.
+
+All Recipient's rights under this Agreement shall terminate if it
+fails to comply with any of the material terms or conditions of this
+Agreement and does not cure such failure in a reasonable period of time
+after becoming aware of such noncompliance. If all Recipient's rights
+under this Agreement terminate, Recipient agrees to cease use and
+distribution of the Program as soon as reasonably practicable. However,
+Recipient's obligations under this Agreement and any licenses granted by
+Recipient relating to the Program shall continue and survive.
+
+Everyone is permitted to copy and distribute copies of this
+Agreement, but in order to avoid inconsistency the Agreement is
+copyrighted and may only be modified in the following manner. The
+Agreement Steward reserves the right to publish new versions (including
+revisions) of this Agreement from time to time. No one other than the
+Agreement Steward has the right to modify this Agreement. The Eclipse
+Foundation is the initial Agreement Steward. The Eclipse Foundation may
+assign the responsibility to serve as the Agreement Steward to a
+suitable separate entity. Each new version of the Agreement will be
+given a distinguishing version number. The Program (including
+Contributions) may always be distributed subject to the version of the
+Agreement under which it was received. In addition, after a new version
+of the Agreement is published, Contributor may elect to distribute the
+Program (including its Contributions) under the new version. Except as
+expressly stated in Sections 2(a) and 2(b) above, Recipient receives no
+rights or licenses to the intellectual property of any Contributor under
+this Agreement, whether expressly, by implication, estoppel or
+otherwise. All rights in the Program not expressly granted under this
+Agreement are reserved.
+
+This Agreement is governed by the laws of the State of New York and
+the intellectual property laws of the United States of America. No party
+to this Agreement will bring a legal action under this Agreement more
+than one year after the cause of action arose. Each party waives its
+rights to a jury trial in any resulting litigation.
+
+
+
+
+[/file]
+[/template]
+
+
diff --git a/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/staticFiles/generateLicenseFiles.mtl b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/staticFiles/generateLicenseFiles.mtl
new file mode 100644
index 00000000..1f6a3e88
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/staticFiles/generateLicenseFiles.mtl
@@ -0,0 +1,12 @@
+[comment encoding = UTF-8 /]
+[module generateLicenseFiles('http://org.eclipse.lyo/oslc4j/adaptorInterface')/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::staticFiles::generateNoticeHTML/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::staticFiles::generateEDLV10HTML/]
+[import org::eclipse::lyo::oslc4j::codegenerator::python::staticFiles::generateEPLV10HTML/]
+
+[template public generateLicenseFiles(traceabilityContext : OclAny)]
+[traceabilityContext.generateNoticeHTML() /]
+[traceabilityContext.generateEDLV10HTML() /]
+[traceabilityContext.generateEPLV10HTML() /]
+[/template]
+
diff --git a/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/staticFiles/generateNoticeHTML.mtl b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/staticFiles/generateNoticeHTML.mtl
new file mode 100644
index 00000000..e3569e67
--- /dev/null
+++ b/org.eclipse.lyo.oslc4j.codegenerator/src/org/eclipse/lyo/oslc4j/codegenerator/python/staticFiles/generateNoticeHTML.mtl
@@ -0,0 +1,117 @@
+[comment encoding = UTF-8 /]
+[module generateNoticeHTML('http://org.eclipse.lyo/oslc4j/adaptorInterface')/]
+
+[template public generateNoticeHTML(traceabilityContext : OclAny)]
+[file ('license/notice.html', false, 'UTF-8')]
+
+
+
+
+
+Eclipse Foundation Software User Agreement
+
+
+
+Eclipse Foundation Software User Agreement
+13 December, 2011
+
+Usage Of Content
+
+THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR OTHER MATERIALS FOR OPEN SOURCE PROJECTS
+ (COLLECTIVELY "CONTENT"). USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND
+ CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW. BY USING THE CONTENT, YOU AGREE THAT YOUR USE
+ OF THE CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR
+ NOTICES INDICATED OR REFERENCED BELOW. IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND
+ CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU MAY NOT USE THE CONTENT.
+
+Applicable Licenses
+
+Unless otherwise indicated, all Content made available by the Eclipse Foundation is provided to you under the terms and conditions of the Eclipse Public License Version 1.0
+ ("EPL"). A copy of the EPL is provided with this Content and is also available at http://www.eclipse.org/legal/epl-v10.html.
+ For purposes of the EPL, "Program" will mean the Content.
+
+Content includes, but is not limited to, source code, object code, documentation and other files maintained in the Eclipse Foundation source code
+ repository ("Repository") in software modules ("Modules") and made available as downloadable archives ("Downloads").
+
+
+ - Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content. Typical modules may include plug-ins ("Plug-ins"), plug-in fragments ("Fragments"), and features ("Features").
+ - Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java™ ARchive) in a directory named "plugins".
+ - A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material. Each Feature may be packaged as a sub-directory in a directory named "features". Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of the Plug-ins
+ and/or Fragments associated with that Feature.
+ - Features may also include other Features ("Included Features"). Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of Included Features.
+
+
+The terms and conditions governing Plug-ins and Fragments should be contained in files named "about.html" ("Abouts"). The terms and conditions governing Features and
+Included Features should be contained in files named "license.html" ("Feature Licenses"). Abouts and Feature Licenses may be located in any directory of a Download or Module
+including, but not limited to the following locations:
+
+
+ - The top-level (root) directory
+ - Plug-in and Fragment directories
+ - Inside Plug-ins and Fragments packaged as JARs
+ - Sub-directories of the directory named "src" of certain Plug-ins
+ - Feature directories
+
+
+Note: if a Feature made available by the Eclipse Foundation is installed using the Provisioning Technology (as defined below), you must agree to a license ("Feature Update License") during the
+installation process. If the Feature contains Included Features, the Feature Update License should either provide you with the terms and conditions governing the Included Features or
+inform you where you can locate them. Feature Update Licenses may be found in the "license" property of files named "feature.properties" found within a Feature.
+Such Abouts, Feature Licenses, and Feature Update Licenses contain the terms and conditions (or references to such terms and conditions) that govern your use of the associated Content in
+that directory.
+
+THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS. SOME OF THESE
+OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):
+
+
+
+IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR TO USE OF THE CONTENT. If no About, Feature License, or Feature Update License is provided, please
+contact the Eclipse Foundation to determine what terms and conditions govern that particular Content.
+
+
+Use of Provisioning Technology
+
+The Eclipse Foundation makes available provisioning software, examples of which include, but are not limited to, p2 and the Eclipse
+ Update Manager ("Provisioning Technology") for the purpose of allowing users to install software, documentation, information and/or
+ other materials (collectively "Installable Software"). This capability is provided with the intent of allowing such users to
+ install, extend and update Eclipse-based products. Information about packaging Installable Software is available at http://eclipse.org/equinox/p2/repository_packaging.html
+ ("Specification").
+
+You may use Provisioning Technology to allow other parties to install Installable Software. You shall be responsible for enabling the
+ applicable license agreements relating to the Installable Software to be presented to, and accepted by, the users of the Provisioning Technology
+ in accordance with the Specification. By using Provisioning Technology in such a manner and making it available in accordance with the
+ Specification, you further acknowledge your agreement to, and the acquisition of all necessary rights to permit the following:
+
+
+ - A series of actions may occur ("Provisioning Process") in which a user may execute the Provisioning Technology
+ on a machine ("Target Machine") with the intent of installing, extending or updating the functionality of an Eclipse-based
+ product.
+ - During the Provisioning Process, the Provisioning Technology may cause third party Installable Software or a portion thereof to be
+ accessed and copied to the Target Machine.
+ - Pursuant to the Specification, you will provide to the user the terms and conditions that govern the use of the Installable
+ Software ("Installable Software Agreement") and such Installable Software Agreement shall be accessed from the Target
+ Machine in accordance with the Specification. Such Installable Software Agreement must inform the user of the terms and conditions that govern
+ the Installable Software and must solicit acceptance by the end user in the manner prescribed in such Installable Software Agreement. Upon such
+ indication of agreement by the user, the provisioning Technology will complete installation of the Installable Software.
+
+
+Cryptography
+
+Content may contain encryption software. The country in which you are currently may have restrictions on the import, possession, and use, and/or re-export to
+ another country, of encryption software. BEFORE using any encryption software, please check the country's laws, regulations and policies concerning the import,
+ possession, or use, and re-export of encryption software, to see if this is permitted.
+
+Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.
+
+
+[/file]
+[/template]
+
+