diff options
author | Aleksandar Kanchev <kanchev@itestra.com> | 2013-05-22 18:35:44 +0200 |
---|---|---|
committer | Aleksandar Kanchev <kanchev@itestra.com> | 2013-06-03 12:00:04 +0200 |
commit | b4e3958b0205e458a8b8fd8e68c1c834cbed0f85 (patch) | |
tree | 0c6ae1f1429ec8a32024abd2661133e8e82e2382 | |
parent | 415b86e90c9674d7b15a432a8cd5ee1b1207ce20 (diff) | |
download | genivi-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.
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 Binary files differnew file mode 100644 index 0000000..3a3d925 --- /dev/null +++ b/org.genivi.commonapi.core/lib/guava-14.0.1.jar 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 +} |