//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);
 }