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