summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksandar Kanchev <kanchev@itestra.com>2013-05-22 18:35:44 +0200
committerAleksandar Kanchev <kanchev@itestra.com>2013-06-03 12:00:04 +0200
commitb4e3958b0205e458a8b8fd8e68c1c834cbed0f85 (patch)
tree0c6ae1f1429ec8a32024abd2661133e8e82e2382
parent415b86e90c9674d7b15a432a8cd5ee1b1207ce20 (diff)
downloadgenivi-common-api-runtime-b4e3958b0205e458a8b8fd8e68c1c834cbed0f85.tar.gz
add support for polymorphic struct types
Until franca supports the new "polymorphic" keyword the annotation "@experimental: polymorphic" can be used. All visible subtypes of a polymorphic struct will be automatically generated polymorphic aswell. The top base struct implements the CommonAPI::SerializablePolymorphicStruct interface and provides a getSerialId() method. The serial id is calculated as hash over all base and member types.
-rw-r--r--org.genivi.commonapi.core/.classpath1
-rw-r--r--org.genivi.commonapi.core/META-INF/MANIFEST.MF2
-rw-r--r--org.genivi.commonapi.core/build.properties3
-rw-r--r--org.genivi.commonapi.core/lib/guava-14.0.1.jarbin0 -> 2189117 bytes
-rw-r--r--org.genivi.commonapi.core/src/org/genivi/commonapi/core/generator/FTypeCollectionGenerator.xtend15
-rw-r--r--org.genivi.commonapi.core/src/org/genivi/commonapi/core/generator/FTypeGenerator.xtend45
-rw-r--r--org.genivi.commonapi.core/src/org/genivi/commonapi/core/generator/FrancaGeneratorExtensions.xtend116
7 files changed, 168 insertions, 14 deletions
diff --git a/org.genivi.commonapi.core/.classpath b/org.genivi.commonapi.core/.classpath
index 406ca4a..3d0ed32 100644
--- a/org.genivi.commonapi.core/.classpath
+++ b/org.genivi.commonapi.core/.classpath
@@ -3,6 +3,7 @@
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="src-gen"/>
<classpathentry kind="src" path="xtend-gen"/>
+ <classpathentry exported="true" kind="lib" path="lib/guava-14.0.1.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="output" path="bin"/>
diff --git a/org.genivi.commonapi.core/META-INF/MANIFEST.MF b/org.genivi.commonapi.core/META-INF/MANIFEST.MF
index c6c242f..8f8168c 100644
--- a/org.genivi.commonapi.core/META-INF/MANIFEST.MF
+++ b/org.genivi.commonapi.core/META-INF/MANIFEST.MF
@@ -16,3 +16,5 @@ Import-Package: javax.inject;version="1.0.0"
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Export-Package: org.genivi.commonapi.core.deployment,
org.genivi.commonapi.core.generator, org.genivi.commonapi.core.preferences
+Bundle-ClassPath: lib/guava-14.0.1.jar,
+ .
diff --git a/org.genivi.commonapi.core/build.properties b/org.genivi.commonapi.core/build.properties
index 4ff3d41..a11e8d2 100644
--- a/org.genivi.commonapi.core/build.properties
+++ b/org.genivi.commonapi.core/build.properties
@@ -2,4 +2,5 @@ source.. = src/,\
src-gen/,\
xtend-gen/
bin.includes = META-INF/,\
- .
+ .,\
+ lib/guava-14.0.1.jar
diff --git a/org.genivi.commonapi.core/lib/guava-14.0.1.jar b/org.genivi.commonapi.core/lib/guava-14.0.1.jar
new file mode 100644
index 0000000..3a3d925
--- /dev/null
+++ b/org.genivi.commonapi.core/lib/guava-14.0.1.jar
Binary files differ
diff --git a/org.genivi.commonapi.core/src/org/genivi/commonapi/core/generator/FTypeCollectionGenerator.xtend b/org.genivi.commonapi.core/src/org/genivi/commonapi/core/generator/FTypeCollectionGenerator.xtend
index b44cb57..eb70ba9 100644
--- a/org.genivi.commonapi.core/src/org/genivi/commonapi/core/generator/FTypeCollectionGenerator.xtend
+++ b/org.genivi.commonapi.core/src/org/genivi/commonapi/core/generator/FTypeCollectionGenerator.xtend
@@ -8,6 +8,7 @@ package org.genivi.commonapi.core.generator
import javax.inject.Inject
import org.eclipse.xtext.generator.IFileSystemAccess
+import org.franca.core.franca.FStructType
import org.franca.core.franca.FTypeCollection
import org.genivi.commonapi.core.deployment.DeploymentInterfacePropertyAccessor
@@ -76,6 +77,10 @@ class FTypeCollectionGenerator {
«generateCommonApiLicenseHeader»
#include "«fTypeCollection.headerFile»"
+ «FOR fStructTypeHeaderPath : fTypeCollection.allDerivedFStructTypeHeaderPaths»
+ #include <«fStructTypeHeaderPath»>
+ «ENDFOR»
+
«fTypeCollection.model.generateNamespaceBeginDeclaration»
namespace «fTypeCollection.name» {
@@ -98,4 +103,14 @@ class FTypeCollectionGenerator {
val hasTypeWithImplementation = fTypeCollection.types.exists[hasImplementation]
return hasTypeWithImplementation
}
+
+ def private getAllDerivedFStructTypeHeaderPaths(FTypeCollection fTypeCollection) {
+ return fTypeCollection.types
+ .filter[it instanceof FStructType && (it as FStructType).isPolymorphic]
+ .map[(it as FStructType).derivedFStructTypes]
+ .flatten
+ .map[(eContainer as FTypeCollection).headerPath]
+ .toSet
+ .filter[!fTypeCollection.headerPath.equals(it)]
+ }
} \ No newline at end of file
diff --git a/org.genivi.commonapi.core/src/org/genivi/commonapi/core/generator/FTypeGenerator.xtend b/org.genivi.commonapi.core/src/org/genivi/commonapi/core/generator/FTypeGenerator.xtend
index a7224cd..0908199 100644
--- a/org.genivi.commonapi.core/src/org/genivi/commonapi/core/generator/FTypeGenerator.xtend
+++ b/org.genivi.commonapi.core/src/org/genivi/commonapi/core/generator/FTypeGenerator.xtend
@@ -6,7 +6,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.genivi.commonapi.core.generator
-import java.util.Arrays
import java.util.Collection
import java.util.HashSet
import java.util.LinkedList
@@ -93,6 +92,15 @@ class FTypeGenerator {
«fStructType.name»(«fStructType.allElements.map[getConstReferenceVariable(fStructType)].join(", ")»);
«ENDIF»
+ «IF fStructType.isPolymorphic»
+ enum: uint32_t { SERIAL_ID = 0x«Integer::toHexString(fStructType.serialId)» };
+
+ static «fStructType.name»* createInstance(const uint32_t& serialId);
+
+ virtual uint32_t getSerialId() const;
+ virtual void createTypeSignature(CommonAPI::TypeOutputStream& typeOutputStream) const;
+ «ENDIF»
+
virtual void readFromInputStream(CommonAPI::InputStream& inputStream);
virtual void writeToOutputStream(CommonAPI::OutputStream& outputStream) const;
@@ -199,6 +207,37 @@ class FTypeGenerator {
}
«ENDIF»
+ «IF fStructType.isPolymorphic»
+ «fStructType.getClassNamespace(parent)»* «fStructType.getClassNamespace(parent)»::createInstance(const uint32_t& serialId) {
+ if (serialId == SERIAL_ID)
+ return new «fStructType.name»;
+
+ «IF fStructType.hasDerivedFStructTypes»
+ const std::function<«fStructType.name»*()> createDerivedInstanceFuncs[] = {
+ «FOR derivedFStructType : fStructType.getDerivedFStructTypes SEPARATOR ','»
+ [&]() { return «derivedFStructType.getRelativeNameReference(fStructType)»::createInstance(serialId); }
+ «ENDFOR»
+ };
+
+ for (auto& createDerivedInstanceFunc : createDerivedInstanceFuncs) {
+ «fStructType.name»* derivedInstance = createDerivedInstanceFunc();
+ if (derivedInstance != NULL)
+ return derivedInstance;
+ }
+
+ «ENDIF»
+ return NULL;
+ }
+
+ uint32_t «fStructType.getClassNamespace(parent)»::getSerialId() const {
+ return SERIAL_ID;
+ }
+
+ void «fStructType.getClassNamespace(parent)»::createTypeSignature(CommonAPI::TypeOutputStream& typeOutputStream) const {
+ «fStructType.name»::writeToTypeOutputStream(typeOutputStream);
+ }
+ «ENDIF»
+
bool operator==(const «fStructType.getClassNamespace(parent)»& lhs, const «fStructType.getClassNamespace(parent)»& rhs) {
if (&lhs == &rhs)
return true;
@@ -342,6 +381,10 @@ class FTypeGenerator {
def private getBaseStructName(FStructType fStructType) {
if (fStructType.base != null)
return fStructType.base.getRelativeNameReference(fStructType)
+
+ if (fStructType.isPolymorphic)
+ return "CommonAPI::SerializablePolymorphicStruct"
+
return "CommonAPI::SerializableStruct"
}
diff --git a/org.genivi.commonapi.core/src/org/genivi/commonapi/core/generator/FrancaGeneratorExtensions.xtend b/org.genivi.commonapi.core/src/org/genivi/commonapi/core/generator/FrancaGeneratorExtensions.xtend
index 0c1988f..867283b 100644
--- a/org.genivi.commonapi.core/src/org/genivi/commonapi/core/generator/FrancaGeneratorExtensions.xtend
+++ b/org.genivi.commonapi.core/src/org/genivi/commonapi/core/generator/FrancaGeneratorExtensions.xtend
@@ -6,11 +6,19 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.genivi.commonapi.core.generator
+import com.google.common.base.Charsets
+import com.google.common.hash.Hasher
+import com.google.common.hash.Hashing
import com.google.common.primitives.Ints
import java.util.List
+import org.eclipse.core.resources.ResourcesPlugin
import org.eclipse.core.runtime.Path
+import org.eclipse.core.runtime.preferences.DefaultScope
+import org.eclipse.core.runtime.preferences.InstanceScope
import org.eclipse.emf.ecore.EObject
import org.eclipse.emf.ecore.resource.Resource
+import org.eclipse.emf.ecore.util.EcoreUtil
+import org.franca.core.franca.FAnnotationType
import org.franca.core.franca.FArrayType
import org.franca.core.franca.FAttribute
import org.franca.core.franca.FBasicTypeId
@@ -30,12 +38,9 @@ import org.franca.core.franca.FUnionType
import org.genivi.commonapi.core.deployment.DeploymentInterfacePropertyAccessor
import org.genivi.commonapi.core.deployment.DeploymentInterfacePropertyAccessor$DefaultEnumBackingType
import org.genivi.commonapi.core.deployment.DeploymentInterfacePropertyAccessor$EnumBackingType
+import org.genivi.commonapi.core.preferences.PreferenceConstants
import static com.google.common.base.Preconditions.*
-import org.eclipse.core.resources.ResourcesPlugin
-import org.eclipse.core.runtime.preferences.InstanceScope
-import org.eclipse.core.runtime.preferences.DefaultScope
-import org.genivi.commonapi.core.preferences.PreferenceConstants
import org.franca.core.franca.FTypedElement
class FrancaGeneratorExtensions {
@@ -370,13 +375,17 @@ class FrancaGeneratorExtensions {
def getStubAdapterClassFireEventMethodName(FBroadcast fBroadcast) {
'fire' + fBroadcast.name.toFirstUpper + 'Event'
}
-
+
def getTypeName(FTypedElement element, EObject source) {
- if ("[]".equals(element.array)) {
- return "std::vector<" + element.type.getNameReference(source) + ">"
- } else {
- return element.type.getNameReference(source)
- }
+ var typeName = element.type.getNameReference(source)
+
+ if (element.type.derived instanceof FStructType && (element.type.derived as FStructType).isPolymorphic)
+ typeName = 'std::shared_ptr<' + typeName + '>'
+
+ if ("[]".equals(element.array))
+ typeName = 'std::vector<' + element.type.getNameReference(source) + '>'
+
+ return typeName
}
def getNameReference(FTypeRef destination, EObject source) {
@@ -560,7 +569,90 @@ class FrancaGeneratorExtensions {
if (fType.actualType.derived != null)
list.add(fType.actualType.derived)
}
-
+
+
+ def boolean isPolymorphic(FStructType fStructType) {
+ if (fStructType.base != null && fStructType.base.isPolymorphic)
+ return true
+
+ if (fStructType.comment != null)
+ return fStructType.comment.elements
+ .filter[type == FAnnotationType::EXPERIMENTAL]
+ .exists[comment.equalsIgnoreCase('polymorphic')]
+
+ return false;
+ }
+
+ def getSerialId(FStructType fStructType) {
+ val hasher = Hashing::murmur3_32.newHasher
+ hasher.putFTypeObject(fStructType);
+ return hasher.hash.asInt
+ }
+
+ def private dispatch void putFTypeObject(Hasher hasher, FStructType fStructType) {
+ if (fStructType.base != null)
+ hasher.putFTypeObject(fStructType.base)
+
+ hasher.putString('FStructType', Charsets::UTF_8)
+ fStructType.elements.forEach[
+ hasher.putFTypeRef(type)
+ // avoid cases where the positions of 2 consecutive elements of the same type are switched
+ hasher.putString(name, Charsets::UTF_8)
+ ]
+ }
+
+ def private dispatch void putFTypeObject(Hasher hasher, FEnumerationType fEnumerationType) {
+ if (fEnumerationType.base != null)
+ hasher.putFTypeObject(fEnumerationType.base)
+
+ hasher.putString('FEnumerationType', Charsets::UTF_8)
+ hasher.putInt(fEnumerationType.enumerators.size)
+ }
+
+ def private dispatch void putFTypeObject(Hasher hasher, FArrayType fArrayType) {
+ hasher.putString('FArrayType', Charsets::UTF_8)
+ hasher.putFTypeRef(fArrayType.elementType)
+ }
+
+ def private dispatch void putFTypeObject(Hasher hasher, FUnionType fUnionType) {
+ if (fUnionType.base != null)
+ hasher.putFTypeObject(fUnionType.base)
+
+ hasher.putString('FUnionType', Charsets::UTF_8)
+ fUnionType.elements.forEach[hasher.putFTypeRef(type)]
+ }
+
+ def private dispatch void putFTypeObject(Hasher hasher, FMapType fMapType) {
+ hasher.putString('FMapType', Charsets::UTF_8)
+ hasher.putFTypeRef(fMapType.keyType)
+ hasher.putFTypeRef(fMapType.valueType)
+ }
+
+ def private dispatch void putFTypeObject(Hasher hasher, FTypeDef fTypeDef) {
+ hasher.putFTypeRef(fTypeDef.actualType)
+ }
+
+ def private void putFTypeRef(Hasher hasher, FTypeRef fTypeRef) {
+ if (fTypeRef.derived != null)
+ hasher.putFTypeObject(fTypeRef.derived)
+ else
+ hasher.putString(fTypeRef.predefined.name, Charsets::UTF_8);
+ }
+
+ def boolean hasDerivedFStructTypes(FStructType fStructType) {
+ return EcoreUtil$UsageCrossReferencer::find(fStructType, fStructType.model.eResource.resourceSet).exists[
+ EObject instanceof FStructType && (EObject as FStructType).base == fStructType
+ ]
+ }
+
+ def getDerivedFStructTypes(FStructType fStructType) {
+ return EcoreUtil$UsageCrossReferencer::find(fStructType, fStructType.model.eResource.resourceSet)
+ .map[EObject]
+ .filter[it instanceof FStructType]
+ .map[it as FStructType]
+ .filter[base == fStructType]
+ }
+
def generateCppNamespace(FModel fModel) '''
«fModel.namespaceAsList.map[toString].join("::")»::'''
@@ -602,4 +694,4 @@ class FrancaGeneratorExtensions {
«getHeader()»
*/
'''
-} \ No newline at end of file
+}