//TODO: This should examine the relationship and determine the multiplicity so that // the relationship can be generated as a sequence rather than single reference. private static bool GenIDL_Relations(Repository repository, Element classElem, TextOutputInterface output, int depth) { bool generatedRelationship = false; foreach (EA.Connector conn in classElem.Connectors) { String annotation = null; String refname = null; String referencedType = GenIDL_GetReferencedTypeToInclude(out annotation, out refname, repository, classElem, conn, output); // textForm.getTextBox().AppendText(" type: " + conn.Type + Environment.NewLine); if (referencedType != null) { output.OutputTextLine(depth, referencedType + " " + refname + "; " + annotation); generatedRelationship = true; } } return generatedRelationship; }
/** Generate IDL4 module corresponding to the UML package * * This function is recursive. It generates IDL for all the nested UML packages and classes * * Returns the number of classes for which IDL could not be generated due to dependencies. * * The IDL for a class "C" can only be generated if we have already generated the IDL for all * the classes "C" depends on. This is determined by the return of the function: * GenIDL_DependenciesAlreadyGenerated() * * A return of "0" indicates there were no relevant classes for which the IDL could not be * generated. That is, the IDL generation is complete. * * A return >0 indicates IDL generation is not complete. In this case the GenIDL_ModuleSecondPass() * could be called again to generate additional classes that may have had their dependent * classes generated in the previous pass. * * If two successive calls to GenIDL_ModuleSecondPass() return the same value. That is, no progress * was made in on pass, this indicates there is a cyclic dependency that cannot be resolved. * In this case the strategy is to report the error so the user can break the dependency by, for example, * declaring on of the dependencies in the link as "@Shared" */ private static int GenIDL_ModuleSecondPass(Repository repository, Package package, bool forceSelection, TextOutputInterface output, int depth, String pathToElem, out int generatedItemCount, HashSet<String> uncheckedElem, Dictionary<long, bool> relevantModules,HashSet<long> completedClasses) { int notGeneratedClassCount = 0; generatedItemCount = 0; // if unckecked skip this model String packageFullName = IDL_FullElementName(pathToElem, package.Name); if ( (!forceSelection) && IsElementUnchecked(uncheckedElem, packageFullName) ) { return 0; } if (!IsModuleRelevant(relevantModules, package, output)) { return 0; } if (completedClasses.Contains(package.PackageID)) { return 0; } String moduleName = IDL_NormalizeUserDefinedClassifierName(package.Name); int moduleOutputPosition = output.GetCurrentPosition(); output.OutputTextLine(depth, "module " + moduleName + " {"); foreach (Element e in package.Elements) { // Skip Enum as they are generated on the first pass if ( !IsElementEnum(e) ) { if (GenIDL_MustGenerateClass(repository, e, packageFullName, uncheckedElem, completedClasses)) { if ( GenIDL_DependenciesAlreadyGenerated(repository, e, output, completedClasses, false) ) { GenIDL_Class(repository, e, output, depth + 1, uncheckedElem, packageFullName); ++generatedItemCount; completedClasses.Add(e.ElementID); } else { ++notGeneratedClassCount; } } } } foreach (Package p in package.Packages) { int subModuleGeneratedItemCount; int submoduleNonGenClassCount = GenIDL_ModuleSecondPass(repository, p, false, output, depth + 1, packageFullName, out subModuleGeneratedItemCount, uncheckedElem, relevantModules, completedClasses); notGeneratedClassCount += submoduleNonGenClassCount; generatedItemCount += subModuleGeneratedItemCount; if (submoduleNonGenClassCount == 0) { // module is complete completedClasses.Add(p.PackageID); } } if (generatedItemCount == 0) { GenIDL_EmptyModuleContent(moduleName, output, depth + 1); output.ClearPositionRange(moduleOutputPosition, output.GetCurrentPosition()); } else { output.OutputTextLine(depth, "}; /* module " + moduleName + " */"); output.OutputTextLine(); } return notGeneratedClassCount; }
private static void GenIDL_Class(Repository repository, Element classElem, TextOutputInterface output, int depth, HashSet<String> uncheckedElem, String elementPath) { // Check if this was a XSD simpleType if so there is nothing to do because we already generated // a typedef for it... if (IsXSDSimpleType(classElem)) { return; } String className = IDL_NormalizeUserDefinedClassifierName(classElem.Name); String baseClassName = null; if (classElem.BaseClasses.Count > 0) { Object obj = classElem.BaseClasses.GetAt(0); Element elem = (Element)obj; baseClassName = GenIDL_GetFullPackageName(repository, elem) + IDL_NormalizeUserDefinedClassifierName(elem.Name); if (baseClassName == null) { output.OutputText(depth, "/* Warning: empty base class ommitted for " + classElem.Name + "*/"); } } // In IDL4 and higher annotations are before the class if (idlVersion >= IDLVersion.IDL_V400) { GenIDL_ClassAnnotation(classElem, output, depth); } output.OutputText(depth, "struct " + className); if (baseClassName != null) { output.OutputText(" : " + baseClassName); } output.OutputTextLine(" {"); bool emptyClassContent = true; if (GenIDL_Attributes(repository, classElem, output, depth + 1)) { emptyClassContent = false; } if (GenIDL_Relations(repository, classElem, output, depth + 1)) { emptyClassContent = false; } if (emptyClassContent) { GenIDL_EmptyClassContent(className, output, depth + 1); } output.OutputText(depth, "};"); // In IDL35 annotations may appear after the class as a comment if (idlVersion < IDLVersion.IDL_V400) { GenIDL_ClassAnnotation(classElem, output, depth); } output.OutputTextLine(); }
private static void GenIDL_ClassTypedef(Element classElem, TextOutputInterface output, int depth) { // output.OutputTextLine(depth, "// Debug Genlinks: " + classElem.Genlinks); // output.OutputTextLine(depth, "// Debug EmbeddedElements count: " + classElem.EmbeddedElements.Count); // Look to see if this class is just an alias for another as would happen for an xsd:simpleType if ( !IsXSDSimpleType(classElem) ) { output.OutputTextLine(depth, "struct " + IDL_NormalizeUserDefinedClassifierName(classElem.Name) + ";"); return; } // Else it is a XSD simpleType. Find the base type and generate a typedef for it String genLinks = classElem.Genlinks; String genLinksBaseClass = null; if (genLinks != null) { String parentIdentifier = "Parent="; int parentBeginIndex = genLinks.IndexOf(parentIdentifier); if (parentBeginIndex >= 0) { parentBeginIndex += parentIdentifier.Length; int parentEndIndex = genLinks.IndexOf(";", parentBeginIndex); if (parentEndIndex < 0) { parentEndIndex = genLinks.Length; } genLinksBaseClass = genLinks.Substring(parentBeginIndex, parentEndIndex - parentBeginIndex); } } if (idlMappingDetail >= IDLMappingDetail.IDL_DETAILS_FULL) { output.OutputTextLine(depth, "/* Mapping to typedef because generated links are: " + genLinks + " */"); } String classifierName = IDL_NormalizeUserDefinedClassifierName(classElem.Name); String typeDeclaration = IDL_XSDbuiltin2IDLdeclaration(classifierName, genLinksBaseClass); if (typeDeclaration != null) { output.OutputTextLine(depth, typeDeclaration); } return; }
internal static void GenIDL(Repository repository, bool isPreview, TextOutputInterface output, HashSet<String> uncheckedElem) { output.Clear(); output.OutputTextLine("/* ******************************************************************* */"); output.OutputTextLine("/* These are UML builtin primitive types that are not primitive in IDL */"); GenIDL_PrebuiltUMLTypes(output); output.OutputTextLine(""); output.OutputTextLine("/* ******************************************************************* */"); output.OutputTextLine("/* These are Types defined in the model */"); output.OutputTextLine(""); // moduleRelevance holds the modules relevant for IDL generation Dictionary<long, bool> moduleRelevance = new Dictionary<long, bool>(); // completedClasses holds the classes for which code has been completely generated // such that we can generate code that depends on these classes HashSet<long> completedClasses = new HashSet<long>(); foreach (Package model in repository.Models) { if ((!isPreview) && uncheckedElem.Contains(model.Name)) { // if unckecked skip this model continue; } UpdateModuleRelevance(moduleRelevance, model, output); } foreach (Package model in repository.Models) { if ((!isPreview) && uncheckedElem.Contains(model.Name)) { // if unckecked skip this model continue; } output.OutputTextLine("/* ----- Model: \"" + model.Name + "\" ----- */"); foreach (Package package in model.Packages) { GenIDL_ModuleFirstPass(repository, package, false, output, 0, model.Name, uncheckedElem, moduleRelevance, completedClasses); } } int notGeneratedClassCount = -1; // Does not matter as long as it is < 0 int previousNotGeneratedClassCount; do { previousNotGeneratedClassCount = notGeneratedClassCount; notGeneratedClassCount = 0; foreach (Package model in repository.Models) { if ((!isPreview) && uncheckedElem.Contains(model.Name)) { // if unckecked skip this model continue; } foreach (Package package in model.Packages) { int generatedItemCount; notGeneratedClassCount += GenIDL_ModuleSecondPass(repository, package, false, output, 0, model.Name, out generatedItemCount, uncheckedElem, moduleRelevance, completedClasses); } } } while ( (notGeneratedClassCount > 0) && (notGeneratedClassCount != previousNotGeneratedClassCount) ) ; if (notGeneratedClassCount > 0 ) { output.OutputTextLine("/* WARNING: " + notGeneratedClassCount + " classes could not be generated due to circular dependencies */"); GenIDL_ReportUngeneratedClasses(repository, output, 0, uncheckedElem, moduleRelevance, completedClasses); } }
/** Outputs the annotations associated with the attribute * * Returns the number of annotations printed */ private static int GenIDL_AttributeAnnotations(EA.Attribute child, TextOutputInterface output, int depth) { string keyAnnotation = "Key"; string[] relevantAnnotationsNoValue = new string[] { keyAnnotation, "must_understand", "autoid", "Optional", "external", "oneway", "ami" }; string[] relevantAnnotationsWithValue = new string[] { "ID", "Value" }; string ddsTag = "DDS"; Boolean mappedToKey = false; int annotationCount = 0; foreach (AttributeTag tag in child.TaggedValues) { String normalizedAnnotation = IDL_NormalizeAnnotationName(tag.Name); // Accept the TagName DDS as an alternative way to provide an accepted no value annotation // So {Tag, Value} = {"DDS", "XYZ"} is equivalent to {"XYZ", } if (normalizedAnnotation.Equals(ddsTag)) { normalizedAnnotation = IDL_NormalizeAnnotationName(tag.Value); } if (relevantAnnotationsNoValue.Contains(normalizedAnnotation)) { GenIDL_Annotation(normalizedAnnotation, annotationCount==0, output, depth); ++annotationCount; if ( normalizedAnnotation.Equals(keyAnnotation) ) { mappedToKey = true; } } else if (relevantAnnotationsWithValue.Contains(normalizedAnnotation)) { GenIDL_Annotation(normalizedAnnotation, tag.Value, annotationCount == 0, output, depth); ++annotationCount; } else { if ((idlMappingDetail >= IDLMappingDetail.IDL_DETAILS_FULL)) { output.OutputTextLine(depth, "/* Skipping unknown annotation name: \"" + tag.Name + "\" value: \"" + tag.Value + "\" */"); } } } // Accept the attributes marked as ID as being "Key" if ( (!mappedToKey) && child.IsID ) { mappedToKey = true; GenIDL_Annotation(keyAnnotation, annotationCount == 0, output, depth); ++annotationCount; if ((idlMappingDetail >= IDLMappingDetail.IDL_DETAILS_FULL)) { output.OutputTextLine(depth, "/* Mapping to @Key because attribute has the IsID property set */"); } } return annotationCount; }
private static void GenIDL_EmptyClassContent(String className, TextOutputInterface output, int depth) { output.OutputTextLine(depth, "octet __dummy_prevent_empty_class;"); }
private static void GenIDL_ReportUngeneratedClasses(Repository repository, TextOutputInterface output, int depth, HashSet<String> uncheckedElem, Dictionary<long, bool> relevantModules, HashSet<long> completedClasses) { output.OutputTextLine("/*"); output.OutputTextLine(" (<package> , <class>) depends on (<package> , <class>) by means of <relationship>"); output.OutputTextLine(" ----------------------------------------------------------------------------------"); foreach (Package model in repository.Models) { if (uncheckedElem.Contains(model.Name)) { // if unchecked skip this model continue; } foreach (Package package in model.Packages) { GenIDL_ReportUngeneratedClasses(repository, package, output, 0, model.Name, uncheckedElem, relevantModules, completedClasses); } } output.OutputTextLine(" -----------------------------------------------------------------------------------"); output.OutputTextLine("*/"); }
private static void GenIDL_ClassTypedef(Element classElem, TextOutputInterface output, int depth) { output.OutputTextLine(depth, "struct " + IDL_NormalizeUserDefinedClassifierName(classElem.Name + ";")); }
/** * Checks that all the definitions this class depends on are already generated * This includes the base classes as well as any types that appear as * attributes and are not marked "@Shared" * */ private static bool GenIDL_DependenciesAlreadyGenerated(Repository repository, Element classElem, TextOutputInterface output, HashSet<long> completedClasses, bool outputReport) { //output.OutputTextLine("// GenIDL_DependenciesAlreadyGenerated Checking: " + classElem.Name); // Check base classes if (classElem.BaseClasses.Count > 0) { Object obj = classElem.BaseClasses.GetAt(0); Element elem = (Element)obj; if (!completedClasses.Contains(elem.ElementID)) { if (outputReport) { output.OutputText(" ( \"" + GenIDL_GetFullPackageName(repository, classElem) + "\" , \"" + classElem.Name + "\" )"); output.OutputText(" depends on ( " + GenIDL_GetFullPackageName(repository, elem) + "\" , \"" + elem.Name + "\" )"); output.OutputTextLine(" dependency: baseclass"); } return false; } } // Check atributes foreach (EA.Attribute child in classElem.Attributes) { if (child.ClassifierID == 0) /* Primitive type */ { continue; } if (!completedClasses.Contains(child.ClassifierID)) { // Not generated yet. It is only OK if this is by reference if ( !IsAttributeReference(child) ) { if (outputReport) { Element childTypeElem = repository.GetElementByID(child.ClassifierID); output.OutputText(" ( \"" + GenIDL_GetFullPackageName(repository, classElem) + "\" , \"" + classElem.Name + "\" )"); output.OutputText(" depends on ( " + GenIDL_GetFullPackageName(repository, childTypeElem) + "\" , \"" + childTypeElem.Name + "\" )"); output.OutputTextLine(" dependency: attribute \"" + child.Name + "\""); } return false; } } } // Check relationships (Aggregations only) foreach (EA.Connector conn in classElem.Connectors) { ConnectorEnd thisElemEnd; ConnectorEnd referencedElemEnd; int referencedElemId; if (classElem.ElementID == conn.ClientID) { thisElemEnd = conn.ClientEnd; referencedElemEnd = conn.SupplierEnd; referencedElemId = conn.SupplierID; } else { thisElemEnd = conn.SupplierEnd; referencedElemEnd = conn.ClientEnd; referencedElemId = conn.ClientID; } if ( (thisElemEnd.Aggregation == 0) || (conn.Type.Equals("Aggregation") == false)) { continue; } if (!referencedElemEnd.IsNavigable) { continue; } if (!completedClasses.Contains(referencedElemId)) { if (outputReport) { Element referencedElem = repository.GetElementByID(referencedElemId); output.OutputText(" ( \"" + GenIDL_GetFullPackageName(repository, classElem) + "\" , \"" + classElem.Name + "\" )"); output.OutputText(" depends on ( " + GenIDL_GetFullPackageName(repository, referencedElem) + "\" , \"" + referencedElem.Name + "\" )"); output.OutputTextLine(" dependency: aggregation \"" + conn.Name + "\""); } return false; } } return true; }
private static int GenIDL_ClassAnnotation(Element classElem, TextOutputInterface output, int depth) { string[] relevantAnnotationsNoValue = new string[] { "autoid", "final", "mutable", "nested", "service" }; string[] relevantAnnotationsWithValue = new string[] { "Extensibility", "verbatim" }; int annotationCount = 0; foreach (TaggedValue tag in classElem.TaggedValues) { String normalizedAnnotation = IDL_NormalizeAnnotationName(tag.Name.ToLower()); if (relevantAnnotationsNoValue.Contains(normalizedAnnotation)) { GenIDL_Annotation(normalizedAnnotation, annotationCount == 0, output, depth); output.OutputTextLine(); ++annotationCount; } else if (relevantAnnotationsWithValue.Contains(normalizedAnnotation)) { GenIDL_Annotation(normalizedAnnotation, tag.Value, annotationCount==0, output, depth); output.OutputTextLine(); ++annotationCount; } } return annotationCount; }
private static void GenIDL_Class(Repository repository, Element classElem, TextOutputInterface output, int depth, HashSet<String> uncheckedElem, String elementPath) { String baseClassName = null; if (classElem.BaseClasses.Count > 0) { Object obj = classElem.BaseClasses.GetAt(0); Element elem = (Element)obj; baseClassName = GenIDL_GetFullPackageName(repository, elem) + IDL_NormalizeUserDefinedClassifierName(elem.Name); } String className = IDL_NormalizeUserDefinedClassifierName(classElem.Name); // In IDL4 and higher annotations are before the class if (idlVersion >= IDLVersion.IDL_V400) { GenIDL_ClassAnnotation(classElem, output, depth); } output.OutputText(depth, "struct " + className); if (baseClassName != null) { output.OutputText(" : " + baseClassName); } output.OutputTextLine(" {"); bool emptyClassContent = true; if (GenIDL_Attributes(repository, classElem, output, depth + 1)) { emptyClassContent = false; } if (GenIDL_Relations(repository, classElem, output, depth + 1)) { emptyClassContent = false; } if (emptyClassContent) { GenIDL_EmptyClassContent(className, output, depth + 1); } output.OutputText(depth, "};"); // In IDL35 annotations may appear after the class as a comment if (idlVersion < IDLVersion.IDL_V400) { GenIDL_ClassAnnotation(classElem, output, depth); } output.OutputTextLine(); }
private static void GenIDL_Annotation( String annotationName, String annotationParam1, bool firstAnnotation, TextOutputInterface output, int depth) { if (idlVersion >= IDLVersion.IDL_V400) { output.OutputText(depth, "@" + annotationName.ToLower()); if (annotationParam1 != null) { output.OutputText("(" + annotationParam1 + ") "); } output.OutputTextLine(); } else if (idlVersion >= IDLVersion.IDL_V350_XTYPES) { output.OutputText(" //@" + annotationName); if (annotationParam1 != null) { output.OutputText("(" + annotationParam1 + ") "); } } else { if (firstAnnotation) { output.OutputText(" //@" + annotationName); } else { output.OutputTextLine(); output.OutputText(depth, " //@" + annotationName); } if (annotationParam1 != null) { output.OutputText(" " + annotationParam1); } } }
/** Outputs UML "primitive" types that are not primitive in IDL */ private static void GenIDL_PrebuiltUMLTypes(TextOutputInterface output) { String builtinTypes = "module UML_Extension {" + Environment.NewLine + " typedef long long dateTime;" + Environment.NewLine + "};"; output.OutputTextLine(builtinTypes); }
private static void GenIDL_EmptyClassContent(String className, TextOutputInterface output, int depth) { output.OutputTextLine(depth, "octet __dummy_prevent_empty_class_" + IDL_NormalizeUserDefinedClassifierName(className) + ";"); }
//TODO: This should examine the relationship and determine the multiplicity so that // the relationship can be generated as a sequence rather than single reference. private static bool GenIDL_Relations(Repository repository, Element classElem, TextOutputInterface output, int depth) { bool generatedRelationship = false; foreach (EA.Connector conn in classElem.Connectors) { List<String> annotations = null; String refname = null; String referencedType = GenIDL_GetReferencedTypeToInclude(out annotations, out refname, repository, classElem, conn, output, depth); if (referencedType != null) { if (annotations != null) { if (idlVersion >= IDLVersion.IDL_V400) { output.OutputText(depth, annotations[0] + " "); for (int i = 1; i < annotations.Count; ++i) { output.OutputText(annotations[i] + " "); } output.OutputTextLine(referencedType + " " + refname + "; "); } else { output.OutputTextLine(depth, referencedType + " " + refname + "; //" + annotations[0]); for (int i=1; i< annotations.Count; ++i) { output.OutputTextLine(depth, "//" + annotations[i]); } } } else { output.OutputTextLine(depth, referencedType + " " + refname + ";"); } generatedRelationship = true; } } return generatedRelationship; }
private static void GenIDL_EmptyModuleContent(String moduleName, TextOutputInterface output, int depth) { output.OutputTextLine(depth, "const long EmptyModule_Sentinel_" + moduleName + " = 0;"); }
private static bool IsModuleRelevant(Dictionary<long, bool> moduleRelevance, Package package, TextOutputInterface output) { bool isRelevant = true; if (!moduleRelevance.TryGetValue(package.PackageID, out isRelevant)) { output.OutputTextLine("IsModuleRelevant; Error did not find: " + package.Name); return true; } return isRelevant; }
private static void GenIDL_Enum(Repository repository, Element enumElem, TextOutputInterface output, int depth, HashSet<String> uncheckedElem, String elementPath) { String enumNameNormalized = IDL_NormalizeUserDefinedClassifierName(enumElem.Name); output.OutputTextLine(depth, "enum " + enumNameNormalized + " {"); //output.OutputTextLine(depth, "/* elementID = " + enumElem.ElementID + " */"); GenIDL_EnumLiterals(repository, enumNameNormalized, enumElem, output, depth + 1); output.OutputTextLine(depth, "};"); }
internal static void GenIDL_Preview(Repository repository, TextOutputInterface output, HashSet<string> uncheckedElem, String fullPath) { char[] delimiterChars = { '\\'}; String[] elementNames = fullPath.Split(delimiterChars); String pathToElement = ""; if (elementNames.Length <= 1) { GenIDL(repository, true, output, uncheckedElem); return; } Package package = (Package)EAUtil_FindChild(repository.Models, elementNames[0]); if (package == null) { output.OutputTextLine("// Could not find selected package: \"" + fullPath + "\" in the model"); return; } Package parentPackage = package; Element classElem = null; for (int i = 1; i < elementNames.Length; ++i, parentPackage = package) { String elemName = elementNames[i]; package = (Package)EAUtil_FindChild(parentPackage.Packages, elemName); if ((package == null) && (i == elementNames.Length - 1)) { classElem = (Element)EAUtil_FindChild(parentPackage.Elements, elemName); } } output.Clear(); if (package == null && classElem == null) { output.OutputTextLine("// Could not find selected element: \"" + fullPath + "\" in the model"); return; } pathToElement = elementNames[0]; for (int i = 1; i < elementNames.Length - 1; ++i) { output.OutputText("module " + IDL_NormalizeUserDefinedClassifierName(elementNames[i]) + " { "); pathToElement += "\\" + elementNames[i]; } output.OutputTextLine(); if (package != null) { // display package // output.OutputTextLine("Displaying Package: " + package.Name); Dictionary<long, bool> moduleRelevance = new Dictionary<long, bool>(); HashSet<long> dummyCompletedClases = new HashSet<long>(); UpdateModuleRelevance(moduleRelevance, package, output); Main.GenIDL_ModuleFirstPass(repository, package, true, output, elementNames.Length - 1, pathToElement, uncheckedElem, moduleRelevance, null); int generatedItemCount; Main.GenIDL_ModuleSecondPass(repository, package, true, output, elementNames.Length - 1, pathToElement, out generatedItemCount, uncheckedElem, moduleRelevance, dummyCompletedClases); } else if (classElem != null) { // display class // output.OutputTextLine("Displaying Class: " + classElem.Name); if (IsElementEnum(classElem)) { Main.GenIDL_Enum(repository, classElem, output, elementNames.Length - 1, uncheckedElem, pathToElement); } else { Main.GenIDL_Class(repository, classElem, output, elementNames.Length - 1, uncheckedElem, pathToElement); } } for (int i = 1; i < elementNames.Length - 1; ++i) { output.OutputText("};"); } }
/* Generate the IDL for an enum literal. */ private static void GenIDL_EnumLiterals(Repository repository, String enumName, Element enumElem, TextOutputInterface output, int depth) { short childCount = enumElem.Attributes.Count; for (short i = 0 ; i < childCount; ++i ) { EA.Attribute child = enumElem.Attributes.GetAt(i); // String typeName = IDL_NormalizeMemberTypeName(child.Type); // Handle enumeration values. The "default value set in UML takes precedence // if not then look at the tag Value int value; String valueAnnotation = null; if (Int32.TryParse(child.Default, out value)) { valueAnnotation = child.Default; // output.OutputText(" //@Value " + child.Default); } else { string[] relevantAnnotationsWithValue = new string[] { "ID", "Value" }; foreach (AttributeTag tag in child.TaggedValues) { String normalizedAnnotation = IDL_NormalizeAnnotationName(tag.Name); if (relevantAnnotationsWithValue.Contains(normalizedAnnotation)) { valueAnnotation = tag.Value; } } } if ( (idlVersion >= IDLVersion.IDL_V400) && (valueAnnotation != null) ) { GenIDL_Annotation("Value", valueAnnotation, true, output, depth); } output.OutputText(depth, enumName + "_" + child.Name); if ((idlVersion == IDLVersion.IDL_V350_CONNEXT52) && (valueAnnotation != null)) { output.OutputText(" = " + valueAnnotation); } if (i < childCount - 1) { output.OutputText(","); } if ((idlVersion == IDLVersion.IDL_V350_XTYPES) && (valueAnnotation != null)) { GenIDL_Annotation("Value", valueAnnotation, true, output, depth); } output.OutputTextLine(); } }
/* Generate the IDL for an attribute. * The attribute can appear by itself, a sequence, or an array. * The determination of this is based on the settings of LowerBound and UpperBound * * UpperBound == 0 ==> Unbounded Sequence * LowerBound == UpperBound == 1 ==> Single member (no Array/Sequence) * LowerBound == 0 && UpperBound == 1 ==> Optional single member * * LowerBound < UpperBound (other values) ==> Bounded Sequence * LowerBound == UpperBound (other values) == > Array * * returns true if it outputs some attribute; otherwise returns false */ private static bool GenIDL_Attributes(Repository repository, Element classElem, TextOutputInterface output, int depth) { if (classElem.Attributes.Count == 0) { return false; } foreach (EA.Attribute child in classElem.Attributes) { // This does not get the fully qualified type name. We need that to fully resolve // the type in the IDL... String typeName; /* This code was trying to get the fully-qualified name but it throws an exception */ if ( child.ClassifierID == 0 ) { typeName = IDL_NormalizeMemberTypeNameClassiffiedID0(child.Type); } else { Element attributeType = repository.GetElementByID(child.ClassifierID); Package attributePackage = repository.GetPackageByID(attributeType.PackageID); typeName = GenIDL_GetFullPackageName(repository, attributeType) + IDL_NormalizeMemberTypeName(attributeType.Name); } //DEBUG:: if (typeName.Equals("dateTime") ) { output.OutputTextLine(depth, "//DEBUG: typeName= " + typeName + " classifiedId= " + child.ClassifierID); } int lower = 0; int upper = 0; try { lower = Convert.ToInt32(child.LowerBound); } catch (Exception) {} try { upper = Convert.ToInt32(child.UpperBound); } catch (Exception) { } int attributeDepth = depth; String effectiveTypeName = typeName; String effectiveMemberName = child.Name; String extraAnnotation = null; if (upper == 0) // Unbounded sequence { //output.OutputText(attributeDepth, "sequence<" + typeName + "> " + child.Name + ";"); effectiveTypeName = "sequence<" + typeName + ">"; if (idlMappingDetail >= IDLMappingDetail.IDL_DETAILS_FULL) { output.OutputTextLine(depth, "// Mapping to unbounded sequence because (upper bound == 0)"); } } else if (lower == upper) { if (upper != 1) // Array { effectiveMemberName = child.Name + "[" + child.UpperBound + "]"; if (idlMappingDetail >= IDLMappingDetail.IDL_DETAILS_FULL) { output.OutputTextLine(depth, "// Mapping to array because (lower bound == upper bound)"); } } } else if (lower == 0 && upper == 1) { // Handle this the same as an @optional annotation extraAnnotation = "Optional"; if (idlMappingDetail >= IDLMappingDetail.IDL_DETAILS_FULL) { output.OutputTextLine(depth, "// Mapping to optional because (lower bound == 0 && upper bound == 1)"); } } else // bounded sequence { effectiveTypeName = "sequence<" + typeName + "," + child.UpperBound + ">"; if (idlMappingDetail >= IDLMappingDetail.IDL_DETAILS_FULL) { output.OutputTextLine(depth, "// Mapping to bounded sequence because (lower bound < upper bound)"); } } GenIDL_AttributeWithAnnotations(child, effectiveTypeName, effectiveMemberName, extraAnnotation, output, depth); output.OutputTextLine(); } return true; }
/** * Given a class (sourceClass) that is being mapped to IDL, this function is invoked on each reference (connector). * that the sourceClass has to determine if the reference/connector should result on a member being added to sourceClass. * * The function returns the fully qualified (and normalized) name for the type referenced by the connector in case * the referenced type needs to be included as a member of the "sourceClass". If there is no member to be included as * a result of the reference/connector the function returns the null string. * * In addition to the name of the referenced element the function returns the annotations that the member should have. * * Paramaters: * - sourceClass. This is the class that is being mapped to IDL * - conn. A connector for sourceClass * - (out) memberName. The member being generated. * type if the multiplicity of the relationship requires that. * - (out) annotations. The annotations on the member. * - (return value) the memberType for memberName. The memberType includes fully-scoped typenames * as well as any needed sequences */ private static String GenIDL_GetReferencedTypeToInclude( out List<String> annotations, out String memberName, Repository repository, Element sourceClass, EA.Connector conn, TextOutputInterface output, int depth) { annotations = null; memberName = null; // Generalization (Inheritance) does not cause the referenced element to // appear as member. This is well understood so no need to report more details on why if (conn.Type.Equals("Generalization")) { return null; } Element referencedElem; ConnectorEnd thisElemEnd; ConnectorEnd referencedElemEnd; int referencedElemId; String explanation; bool includeReferencedTypeAsMember; bool includeAsReference; bool reportExplanationText = idlMappingDetail >= IDLMappingDetail.IDL_DETAILS_BASIC; // This resolves the details of the reference and determines whether a member should be // generated of not. GenIDL_ReferenceDescriptor(repository, conn, sourceClass.ElementID, reportExplanationText, out thisElemEnd, out referencedElemEnd, out referencedElemId, out referencedElem, out memberName, out includeAsReference, out includeReferencedTypeAsMember, out explanation); if ( !includeReferencedTypeAsMember ) { if ( reportExplanationText ) { String referencedElementClassName = "Unknown Type"; if (referencedElem != null) { referencedElementClassName = referencedElem.Name; } output.OutputTextLine(depth, "/* Skipping reference \"" + memberName + "\" to element \"" + referencedElementClassName + "\" because " + explanation + " */"); } return null; } /* If we are here we know includeReferencedTypeAsMember == TRUE * this means referenced class as a member of this element * and also that referencedElem != null as this is checked by GenIDL_ReferenceDescriptor() */ String memberTypeScoped = null; String cardinality = referencedElemEnd.Cardinality; String normalizedMemberType = IDL_NormalizeMemberTypeName(referencedElem.Name); memberTypeScoped = GenIDL_GetFullPackageName(repository, referencedElem) + normalizedMemberType; // Apply cardinality rules. Can cause member to be @Optional, or a sequence if (cardinality.Equals("0..1")) { // Zero or one -> Optional if (annotations == null ) { annotations = new List<String>(); } annotations.Add("@Optional"); if (idlMappingDetail >= IDLMappingDetail.IDL_DETAILS_FULL) { output.OutputTextLine(depth, "/* Mapping to Optional because relation cardinality == \"0..1\" */"); } } else if (cardinality.Equals("*") || cardinality.EndsWith("..*") || cardinality.EndsWith("..")) { // No upper limit -> unbounded sequence memberTypeScoped = "sequence<" + memberTypeScoped + ">"; if (idlMappingDetail >= IDLMappingDetail.IDL_DETAILS_FULL) { output.OutputTextLine(depth, "/* Mapping to unbounded sequence because relation cardinality is \"*\", \"..*\", or \"..\" */"); } } else if (cardinality.Equals("") || cardinality.Equals("1") || cardinality.Equals("0")) { // Map to regular member. No sequence, no optional if (idlMappingDetail >= IDLMappingDetail.IDL_DETAILS_FULL) { output.OutputTextLine(depth, "/* Mapping to regular member because relation cardinality is \"\", \"1\", or \"0\" */"); } } else { // Bounded sequence int upperLimit = 0; if (Int32.TryParse(cardinality, out upperLimit)) { if (upperLimit <= 0) { upperLimit = 1; } memberTypeScoped = "sequence<" + memberTypeScoped + "," + upperLimit + ">"; if (idlMappingDetail >= IDLMappingDetail.IDL_DETAILS_FULL) { output.OutputTextLine(depth, "/* Mapping to bounded sequence because relationship cardinality = " + cardinality + " (lower bound < upper bound) */"); } } else { int limitPos = cardinality.LastIndexOf(".."); if ((limitPos != -1) && Int32.TryParse(cardinality.Substring(limitPos + 2), out upperLimit)) { memberTypeScoped = "sequence<" + memberTypeScoped + "," + upperLimit + ">"; if (idlMappingDetail >= IDLMappingDetail.IDL_DETAILS_FULL) { output.OutputTextLine(depth, "/* Mapping to bounded sequence because relationship cardinality = " + cardinality + " (lower bound < upper bound) */"); } } else { memberTypeScoped = "sequence<" + memberTypeScoped + ">"; if (idlMappingDetail >= IDLMappingDetail.IDL_DETAILS_FULL) { output.OutputTextLine(depth, "/* Mapping to unbounded sequence because relationship cardinality = " + cardinality + " */"); } } } } // Members included by reference are mapped to the @Shared annotation if (includeAsReference) { if (idlVersion == IDLVersion.IDL_V350_CONNEXT52) { memberTypeScoped = memberTypeScoped + "*"; } else // Otherwise use an annotation { if (annotations == null) { annotations = new List<String>(); } annotations.Add("@Shared"); } if (idlMappingDetail >= IDLMappingDetail.IDL_DETAILS_FULL) { output.OutputTextLine(depth, "/* Mapping to Shared because Containment is 'Reference' or Aggregation is 'Shared' */"); } } return memberTypeScoped; }
private static int GenIDL_ClassAnnotation(Element classElem, TextOutputInterface output, int depth) { string[] relevantAnnotationsNoValue = new string[] { "autoid", "final", "mutable", "extensible", "service" }; string[] relevantAnnotationsWithValue = new string[] { "Extensibility", "verbatim", "nested" }; string ddsTag = "DDS"; int annotationCount = 0; foreach (TaggedValue tag in classElem.TaggedValues) { String normalizedAnnotation = IDL_NormalizeAnnotationName(tag.Name); // Accept the TagName DDS as an alternative way to provide an accepted no value annotation // So {Tag, Value} = {"DDS", "XYZ"} is equivalent to {"XYZ", } if (normalizedAnnotation.Equals(ddsTag)) { normalizedAnnotation = IDL_NormalizeAnnotationName(tag.Value); } if (relevantAnnotationsNoValue.Contains(normalizedAnnotation)) { GenIDL_Annotation(normalizedAnnotation, annotationCount == 0, output, depth); output.OutputTextLine(); ++annotationCount; } else if (relevantAnnotationsWithValue.Contains(normalizedAnnotation)) { GenIDL_Annotation(normalizedAnnotation, tag.Value, annotationCount == 0, output, depth); output.OutputTextLine(); ++annotationCount; } else { if ((idlMappingDetail >= IDLMappingDetail.IDL_DETAILS_FULL)) { output.OutputTextLine(depth, "/* Skipping unknown annotation name:\"" + tag.Name + "\" value: \"" + tag.Value + "\" */"); } } } return annotationCount; }
/** Generate IDL4 module corresponding to the UML package * * This function is the first-pass module generation. It generates the things that * have no dependencies on anything else and help resolve dependencies for the types * that depend on this module. These are: * * enums * typedefs for all structures defined in the module. * * This function is recursive. It generates IDL for all the nested UML packages as well * * */ private static void GenIDL_ModuleFirstPass(Repository repository, Package package, bool forceSelection, TextOutputInterface output, int depth, String pathToElem, HashSet<String> uncheckedElem, Dictionary<long, bool> relevantModules, HashSet<long> completedClasses) { // if unckecked skip this model String packageFullName = IDL_FullElementName(pathToElem, package.Name); if ( (!forceSelection) && IsElementUnchecked(uncheckedElem, packageFullName)) { return; } if ( !IsModuleRelevant(relevantModules, package, output) ) { if (idlMappingDetail >= IDLMappingDetail.IDL_DETAILS_FULL) { output.OutputTextLine(depth, "/* Skipping empty module: \"" + package.Name + "\" */"); } return; } String moduleName = IDL_NormalizeUserDefinedClassifierName(package.Name); bool emptyModuleContent = true; output.OutputTextLine(depth, "module " + moduleName + " {"); foreach (Element e in package.Elements) { if (IsElementUnchecked(uncheckedElem, packageFullName, e.Name)) { continue; } if (IsElementEnum(e)) { GenIDL_Enum(repository, e, output, depth + 1, uncheckedElem, packageFullName); if ( completedClasses != null ) { completedClasses.Add(e.ElementID); } emptyModuleContent = false; } else { if (GenIDL_MustGenerateClass(repository, e, packageFullName, uncheckedElem, null)) { GenIDL_ClassTypedef(e, output, depth + 1); emptyModuleContent = false; } } } foreach (Package p in package.Packages) { GenIDL_ModuleFirstPass(repository, p, false, output, depth + 1, packageFullName, uncheckedElem, relevantModules, completedClasses); emptyModuleContent = false; } if (emptyModuleContent) { GenIDL_EmptyModuleContent(moduleName, output, depth + 1); } output.OutputTextLine(depth, "}; /* module " + moduleName + " */"); output.OutputTextLine(); }
/** * Checks that all the definitions this class depends on are already generated * This includes the base classes as well as any types that appear as * attributes and are not marked "@Shared" * */ private static bool GenIDL_DependenciesAlreadyGenerated(Repository repository, Element classElem, TextOutputInterface output, HashSet<long> completedClasses, bool outputReport) { //output.OutputTextLine("// GenIDL_DependenciesAlreadyGenerated Checking: " + classElem.Name); // Check base classes if (classElem.BaseClasses.Count > 0) { Object obj = classElem.BaseClasses.GetAt(0); Element elem = (Element)obj; if (!completedClasses.Contains(elem.ElementID)) { if (outputReport) { output.OutputText(" ( \"" + GenIDL_GetFullPackageName(repository, classElem) + "\" , \"" + classElem.Name + "\" )"); output.OutputText(" depends on ( " + GenIDL_GetFullPackageName(repository, elem) + "\" , \"" + elem.Name + "\" )"); output.OutputTextLine(" dependency: baseclass"); } return false; } } // Check atributes foreach (EA.Attribute child in classElem.Attributes) { if (child.ClassifierID == 0) /* Primitive type */ { continue; } if (!completedClasses.Contains(child.ClassifierID)) { // Not generated yet. It is only OK if this is by reference if ( !IsAttributeReference(child) ) { if (outputReport) { Element childTypeElem = repository.GetElementByID(child.ClassifierID); output.OutputText(" ( \"" + GenIDL_GetFullPackageName(repository, classElem) + "\" , \"" + classElem.Name + "\" )"); output.OutputText(" depends on ( " + GenIDL_GetFullPackageName(repository, childTypeElem) + "\" , \"" + childTypeElem.Name + "\" )"); output.OutputTextLine(" dependency: attribute \"" + child.Name + "\""); } return false; } } } // Check relationships (Aggregations only) String explanation; foreach (EA.Connector conn in classElem.Connectors) { ConnectorEnd thisElemEnd; ConnectorEnd referencedElemEnd; int referencedElemId; Element referencedElem; bool includeReferencedTypeAsMember; String memberName; bool includeAsReference; // Resolve the reference but ommit any explanatory text GenIDL_ReferenceDescriptor(repository, conn, classElem.ElementID, false, out thisElemEnd, out referencedElemEnd, out referencedElemId, out referencedElem, out memberName, out includeAsReference, out includeReferencedTypeAsMember, out explanation); // If the reference did not have to be included, there there is no dependency on it. if ( includeReferencedTypeAsMember == false ) { continue; } // If we are here then the referenced element must appear as a member. There is a depedency so we must make sure // that that class has already been generated if (!completedClasses.Contains(referencedElemId)) { if (outputReport) { output.OutputText(" ( \"" + GenIDL_GetFullPackageName(repository, classElem) + "\" , \"" + classElem.Name + "\" )"); output.OutputText(" depends on ( " + GenIDL_GetFullPackageName(repository, referencedElem) + "\" , \"" + referencedElem.Name + "\" )"); output.OutputTextLine(" dependency: aggregation \"" + memberName + "\""); } return false; } } return true; }
/** Outputs UML "primitive" types that are not primitive in IDL */ private static void GenIDL_PrebuiltUMLTypes(TextOutputInterface output) { String builtinTypes = "struct dateTime { long date; long time; };"; output.OutputTextLine(builtinTypes); }