Ejemplo n.º 1
0
 private void CompileMif(MohawkCollege.EHR.HL7v3.MIF.MIF20.Repository.PackageRepository pkr, ClassRepository rep)
 {
     
     MohawkCollege.EHR.gpmr.Pipeline.Compiler.Mif20.Compilers.RepositoryCompiler util = new MohawkCollege.EHR.gpmr.Pipeline.Compiler.Mif20.Compilers.RepositoryCompiler(pkr);
     util.ClassRepository = rep;
     util.Compile();
 }
        /// <summary>
        /// Create a class element
        /// </summary>
        /// <param name="modelElement"></param>
        /// <param name="gsm"></param>
        /// <returns></returns>
        private ModelElement CreateFlatModelElement(MohawkCollege.EHR.HL7v3.MIF.MIF20.ModelElement modelElement, GlobalStaticModel gsm)
        {
            if (modelElement is SerializedClass)
                return CreateFlatClass(modelElement as SerializedClass, gsm);
            else if (modelElement is SerializedCommonModelElementRef)
                return CreateFlatCMETRef(modelElement as SerializedCommonModelElementRef, gsm);
            else
                return modelElement;

        }
Ejemplo n.º 3
0
        /// <summary>
        /// Parse a COR state transition from a MIF 2.0 state transition
        /// </summary>
        private static StateTransition Parse(MohawkCollege.EHR.HL7v3.MIF.MIF20.Transition tx, Dictionary<string, State> tStates)
        {
            StateTransition retVal = new StateTransition();

            // Parse
            retVal.Name = tx.Name;
            retVal.StartState = tStates[tx.StartStateName];
            retVal.EndState = tStates[tx.EndStateName];

            return retVal;
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Parse a COR state machine from a MIF state machine
        /// </summary>
        internal static MohawkCollege.EHR.gpmr.COR.StateMachine Parse(MohawkCollege.EHR.HL7v3.MIF.MIF20.StateMachine StateMachine)
        {
            MohawkCollege.EHR.gpmr.COR.StateMachine retVal = new MohawkCollege.EHR.gpmr.COR.StateMachine();

            retVal.Transitions = new List<MohawkCollege.EHR.gpmr.COR.StateTransition>();
            Dictionary<String, MohawkCollege.EHR.gpmr.COR.State> tStates = new Dictionary<String, MohawkCollege.EHR.gpmr.COR.State>();
            retVal.States = new Dictionary<string, MohawkCollege.EHR.gpmr.COR.State>();

            // Sort each state
            StateMachine.SubState.Sort(new MohawkCollege.EHR.HL7v3.MIF.MIF20.State.Comparator());

            // Parse States
            foreach (MohawkCollege.EHR.HL7v3.MIF.MIF20.State st in StateMachine.SubState)
            {
                MohawkCollege.EHR.gpmr.COR.State nst = Parse(st);
                tStates.Add(nst.Name, nst);
            }

            // Sort parent/child states
            foreach (KeyValuePair<String, MohawkCollege.EHR.gpmr.COR.State> kv in tStates)
            {
                if (kv.Value.ParentStateName == null) // No parent? Its at the root
                    retVal.States.Add(kv.Key, kv.Value);
                else
                {
                    if (tStates[kv.Value.ParentStateName].ChildStates == null) tStates[kv.Value.ParentStateName].ChildStates = new Dictionary<string, State>();
                    tStates[kv.Value.ParentStateName].ChildStates.Add(kv.Key, kv.Value);
                }
            }

            // Parse Transitions
            foreach (MohawkCollege.EHR.HL7v3.MIF.MIF20.Transition tx in StateMachine.Transition)
                retVal.Transitions.Add(Parse(tx, tStates));

            return retVal;
        }
Ejemplo n.º 5
0
        public void Render(string OwnerNS, string apiNs, MohawkCollege.EHR.gpmr.COR.Feature f, System.IO.TextWriter tw)
        {

            StringWriter sw = new StringWriter();

            // Make a strong typed reference to enumeration
            Enumeration enu = f as Enumeration;

            // enumeration is a concept domain? do the binding
            if (enu is ConceptDomain && (enu as ConceptDomain).ContextBinding != null)
                enu = (enu as ConceptDomain).ContextBinding[0];
            else if(enu is ConceptDomain)
                throw new InvalidOperationException("Won't render unbound concept domains");
            
            #region Usings

            // Validate Usings
            string[] usings = new string[] { "Attributes", "Interfaces", "DataTypes" };
            foreach (string s in usings)
                sw.WriteLine("using {1}.{0};", s, apiNs);
            sw.WriteLine("using System.ComponentModel;");
            #endregion

            sw.WriteLine("namespace {0}.Vocabulary {{", OwnerNS); // start ns

            // Generate the documentation
            if (DocumentationRenderer.Render(enu.Documentation, 1).Length == 0)
                sw.WriteLine("\t/// <summary>{0}</summary>", enu.BusinessName ?? "No Documentation Found");
            else
                sw.Write(DocumentationRenderer.Render(enu.Documentation, 1));


            // Generate the structure attribute
            sw.WriteLine("\t[Structure(Name = \"{0}\", CodeSystem = \"{1}\", StructureType = StructureAttribute.StructureAttributeType.{2}, Publisher = {3})]", enu.Name, enu.ContentOid, enu.GetType().Name, enu.Documentation != null ? "\"" + enu.Documentation.Copyright + "\"" : "null");
            sw.WriteLine("#if !WINDOWS_PHONE");
            sw.WriteLine("\t[Serializable]");
            sw.WriteLine("#endif");

            string renderName = enu.Name;
            if (enu.Annotations != null && enu.Annotations.Exists(o => o is RenderAsAnnotation))
                renderName = (enu.Annotations.Find(o => o is RenderAsAnnotation) as RenderAsAnnotation).RenderName;

            // Generate enum
            sw.WriteLine("\tpublic enum {0} {{ ", Util.Util.MakeFriendly(renderName));

            List<String> rendered = new List<string>(),
                mnemonics = new List<string>();
            RenderLiterals(sw, enu, rendered, mnemonics,  enu.Literals);
            
            String tStr = sw.ToString();
            tStr = tStr.Remove(tStr.LastIndexOf(","));
            tStr += ("\r\n\t}");
            tStr += ("\r\n}"); // end ns

            // Write to tw
            tw.Write(tStr);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Update legalization information
        /// </summary>
        internal static void UpdateLegalInfo(MohawkCollege.EHR.gpmr.COR.Documentation documentation, Header header)
        {
            // Add legalese and other fun stuff
            if (header.Contributor != null)
            {
                documentation.Contributors = new List<string>(header.Contributor.Count);
                foreach (var kv in header.Contributor)
                    documentation.Contributors.Add(String.Format("{0}: {1} ({2})", kv.Role, kv.Name.Name, kv.Affiliation));
            }
            // Disclaimer
            if (header.Copyright != null && header.Copyright.Disclaimer != null)
            {
                documentation.Disclaimer = new List<string>();
               foreach (XmlElement xel in header.Copyright.Disclaimer.MarkupElements ?? new List<XmlElement>().ToArray())
                    documentation.Disclaimer.Add(xel.OuterXml.Replace(" xmlns:html=\"http://www.w3.org/1999/xhtml\"", "").Replace("html:", "")); // Clean mif doc data from docs
                if (header.Copyright.Disclaimer.MarkupText != null) documentation.Disclaimer.Add(header.Copyright.Disclaimer.MarkupText);
            }
            // Disclaimer
            if (header.Copyright != null && header.Copyright.LicenseTerms != null)
            {
                documentation.LicenseTerms = new List<string>();
                foreach (XmlElement xel in header.Copyright.LicenseTerms.MarkupElements ?? new List<XmlElement>().ToArray())
                    documentation.LicenseTerms.Add(xel.OuterXml.Replace(" xmlns:html=\"http://www.w3.org/1999/xhtml\"", "").Replace("html:", "")); // Clean mif doc data from docs
                if (header.Copyright.LicenseTerms.MarkupText != null) documentation.LicenseTerms.Add(header.Copyright.LicenseTerms.MarkupText);
            }

         }
Ejemplo n.º 7
0
        /// <summary>
        /// Renders feature <paramref name="f"/> to <paramref name="tw"/> in the specified <paramref name="OwnerNS"/>
        /// </summary>
        /// <param name="apiNs">The namespace to render the api in</param>
        /// <param name="f">The feature (class) being rendered</param>
        /// <param name="ownerPackage">The package the class is to be rendered in</param>
        /// <param name="tw">The textwriter to write to</param>
        public void Render(string ownerPackage, string apiNs, MohawkCollege.EHR.gpmr.COR.Feature f, System.IO.TextWriter tw)
        {
            s_imports.Clear();
            // Validate arguments
            if (String.IsNullOrEmpty(ownerPackage))
                throw new ArgumentNullException("ownerPackage");
            if (String.IsNullOrEmpty(apiNs))
                throw new ArgumentNullException("apiNs");
            if (f == null || !(f is Class))
                throw new ArgumentException("Parameter must be of type Class", "f");

            // Create a local copy of the class
            Class cls = f as Class;

            StringWriter sw = new StringWriter();

            tw.WriteLine("package {0}.{1};", ownerPackage, cls.ContainerName.ToLower());


            #region Render Class Signature

            // Documentation
            if (DocumentationRenderer.Render(cls.Documentation, 0).Length == 0)
                sw.WriteLine("\t/** No Summary Documentation Found */");
            else
                sw.Write(DocumentationRenderer.Render(cls.Documentation, 0));

            // Create structure annotation
            sw.WriteLine(CreateStructureAnnotation(cls));

            // Create class signature
            sw.Write("public {1} class {0}", Util.Util.PascalCase(cls.Name), cls.IsAbstract ? "abstract" : "");

            // If class is generic class
            string genericString = String.Empty;
            foreach (TypeParameter tp in cls.TypeParameters ?? new List<TypeParameter>())
                genericString += tp + ",";
            if (!String.IsNullOrEmpty(genericString))
                sw.Write("<{0}>", genericString.Substring(0, genericString.Length - 1)); // get rid of trailing ,

            sw.Write(" extends ");

            // Base class? 
            if (String.Format("{0}.rim.", ownerPackage) + Util.Util.MakeFriendly(cls.Name) == RimbaJavaRenderer.RootClass) // This class is the root
                sw.Write("java.lang.Object");
            else if (cls.BaseClass != null)
                sw.Write("{0}.{1}.{2}", ownerPackage, cls.BaseClass.Class.ContainerName.ToLower(), Util.Util.PascalCase(cls.BaseClass.Class.Name));
            else
                sw.Write("{0}", RimbaJavaRenderer.RootClass);

            // Interfaces
            sw.Write(" implements IGraphable ");
            List<String> interfaces = MohawkCollege.EHR.gpmr.Pipeline.Renderer.Java.HeuristicEngine.Interfaces.MapInterfaces(cls, ownerPackage);
            if (interfaces.Count > 0)
            {
                sw.Write(",");
                foreach (string s in interfaces)
                    sw.Write("{0} {1}", s, s == interfaces.Last() ? "" : ",");
            }

            sw.WriteLine("{");

            #endregion

            #region Render Properties

            // Get the content up the tree

            List<ClassContent> content = new List<ClassContent>(cls.Content);
            var c = cls.BaseClass;
            while (c != null && c.Class != null)
            {
                foreach (var itm in c.Class.Content)
                {
                    if (content.Exists(o => o.Name == itm.Name)) continue;
                    var addItm = itm.Clone() as ClassContent;
                    addItm.Container = cls; // set the container
                    content.Add(addItm);
                }
                c = c.Class.BaseClass;
            }
            // Sort
            content.Sort(new ClassContent.Comparator());

            int propertySort = 0;
            foreach (ClassContent cc in content)
                sw.WriteLine(RenderClassContent(cc, ownerPackage, propertySort++));

            #endregion

            if (!cls.IsAbstract)
            {
                #region Constructors

                sw.WriteLine("\t/** Default CTOR */");
                sw.WriteLine("\tpublic {0}() {{ super(); }}\r\n", Util.Util.PascalCase(cls.Name));

                Dictionary<String, String[]> ctors = CreateFactoryMethod(cls.CreateTypeReference(), "this", ownerPackage);

                // Write CTOR
                List<String> wroteParms = new List<string>(); // Keep track of the parameters used
                foreach (KeyValuePair<String, String[]> kv in ctors)
                {
                    if (kv.Value[0].Length > 0 && !wroteParms.Contains(kv.Value[0]))
                    {
                        wroteParms.Add(kv.Value[0]);
                        sw.WriteLine("\t/** Constructor for all {0} elements\r\n\t * ", kv.Key);
                        sw.WriteLine(kv.Value[2]);
                        sw.WriteLine("\t*/");
                        sw.WriteLine("\tpublic {0}({1}) {{ \r\n\t\tsuper();\r\n{2}\t}}", Util.Util.PascalCase(cls.Name), kv.Value[0].Substring(0, kv.Value[0].Length - 1), kv.Value[1]);
                    }
                }

                #endregion

                //#region Generate Collapsed Constructor

                //sw.WriteLine(CreateCollapsedConstructor(cls, OwnerNs));

                //#endregion
            }

            // Move to a factory
            // Is this an emtpy class that facilitates a choice?
            if (cls.SpecializedBy != null && cls.SpecializedBy.Count > 0 &&
                cls.IsAbstract)
            {
                foreach (TypeReference tr in CascadeSpecializers(cls.SpecializedBy))
                {
                    // Is method
                    if (tr.Class == null || tr.Class.ContainerName == "RIM" && !RimbaJavaRenderer.GenerateRim ||
                        tr.Class.IsAbstract)
                        continue;


                    sw.WriteLine("\t\t/** Returns true if this abstract class instance is an instance of {0}.{1}.{2} */\r\n\t\tpublic boolean is{1}{2}() {{ ", ownerPackage, tr.Class.ContainerName, Util.Util.PascalCase(tr.Class.Name));
                    sw.WriteLine("\t\t\treturn this.getClass().getName().equals(\"{0}.{1}.{2}\");", ownerPackage, tr.Class.ContainerName.ToLower(), Util.Util.PascalCase(tr.Class.Name));
                    sw.WriteLine("\t\t}");
                }
            }
            //    // NB: This isn't possible in Java (at least I don't have time to work around Java's weirdness) so
            //    //      I'm going to disable it. This causes problems when
            //    //
            //    //      abstract A.A
            //    //      abstract B.B extends A.A
            //    //      C.C extends A.A
            //    //      B.C extends B.B
            //    //
            //    // Results in :
            //    //     A.A { C.C CreateC(); }
            //    //     B.B { B.C CreateC(); }
            //    //
            //    // Java freaks out because the return type of CreateC has changed.
            //    // The only thing I can think of is to blow out the method name...
            //    // wait a tick, I'll do that :@

            //    //#region Generate creator methods for each of the children

            //    //// NB: In Java apparently super classes' static methods are acceessable
            //    ////     in child classes which is different than .NET, so we're not going to cascade specializers
            //    foreach (TypeReference tr in cls.SpecializedBy)
            //    {

            //        if (tr.Class == null || tr.Class.ContainerName == "RIM" && !RimbaJavaRenderer.GenerateRim ||
            //            tr.Class.IsAbstract)
            //            continue;

            //        Class child = tr.Class;

            //        // Create factory for the child
            //        Dictionary<String, String[]> ctors = CreateFactoryMethod(tr, "retVal", ownerPackage);
            //        // Write factory
            //        foreach (var kv in ctors)
            //        {

            //            string methodSignature = String.Format("{1}.{0}.{2}.create{3}", cls.ContainerName, ownerPackage, Util.Util.PascalCase(cls.Name), Util.Util.PascalCase(child.Name)),
            //                publicName = methodSignature;

            //            // Regex for extracting the parameter type rather than the type/name
            //            Regex parmRegex = new Regex(@"(([\w<>,.]*)\s(\w*)),?\s?");
            //            MatchCollection parmMatches = parmRegex.Matches(kv.Value[0]);
            //            foreach (Match match in parmMatches)
            //                methodSignature += match.Groups[1].Value.Substring(0, match.Groups[1].Value.IndexOf(" "));


            //            // JF: Added to protected against rendering the same factory method
            //            if (s_methodDeclarations.Contains(methodSignature))
            //                continue;
            //            s_methodDeclarations.Add(methodSignature);

            //            // Render if there is even any content
            //            if (kv.Value[0].Length > 0)
            //            {
            //                string clsDoc = DocumentationRenderer.Render(child.Documentation, 1);

            //                string ctorClassName = String.Format("{0}.{2}.{1}", ownerPackage, tr.Class.Name, tr.Class.ContainerName.ToLower());
            //                //// import already exists?
            //                //if(!s_imports.Exists(o=>o.EndsWith(Util.Util.PascalCase(tr.Class.Name))))
            //                //{
            //                //    s_imports.Add(ctorClassName);
            //                //    ctorClassName = ctorClassName.Substring(ctorClassName.LastIndexOf(".") + 1);
            //                //}
            //                //if (s_imports.Contains(ctorClassName))
            //                //    ctorClassName = ctorClassName.Substring(ctorClassName.LastIndexOf(".") + 1);

            //                if (clsDoc.Contains("*/"))
            //                    sw.Write(clsDoc.Substring(0, clsDoc.LastIndexOf("*/")));
            //                sw.WriteLine("* This function creates a new instance of {5}.{1}\r\n\t {4}\r\n\t*/\t\n\tpublic static {0} create{6}{2}({3}) {{ ", ctorClassName, tr.Class.Name, Util.Util.PascalCase(child.Name), kv.Value[0].Substring(0, kv.Value[0].Length - 1), kv.Value[2], tr.Class.ContainerName.ToLower(), Util.Util.PascalCase(cls.Name));
            //                sw.WriteLine("\t\t{0} retVal = new {0}();", ctorClassName);
            //                sw.WriteLine("{0}", kv.Value[1]);
            //                sw.WriteLine("\t\treturn retVal;");
            //                sw.WriteLine("\t}");

            //                if (!factoryMethods.ContainsKey(tr.Name))
            //                    factoryMethods.Add(tr.Name, new List<FactoryMethodInfo>());

            //                FactoryMethodInfo myInfo = new FactoryMethodInfo(publicName, kv.Value[2], methodSignature);


            //                //Match the regular expression below and capture its match into backreference number 1 «(([\w<>,]*?)\s(\w*),?\s?)»
            //                //Match the regular expression below and capture its match into backreference number 2 «([\w<>,]*?)»
            //                //Match a single character present in the list below «[\w<>,]*?»
            //                //Between zero and unlimited times, as few times as possible, expanding as needed (lazy) «*?»
            //                //A word character (letters, digits, etc.) «\w»
            //                //One of the characters “<>,” «<>,»
            //                //Match a single character that is a “whitespace character” (spaces, tabs, line breaks, etc.) «\s»
            //                //Match the regular expression below and capture its match into backreference number 3 «(\w*)»
            //                //Match a single character that is a “word character” (letters, digits, etc.) «\w*»
            //                //Between zero and unlimited times, as many times as possible, giving back as needed (greedy) «*»
            //                //Match the character “,” literally «,?»
            //                //Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
            //                //Match a single character that is a “whitespace character” (spaces, tabs, line breaks, etc.) «\s?»
            //                //Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
            //                foreach (Match match in parmMatches)
            //                    myInfo.parameters.Add(match.Groups[1].Value);

            //                // ADd the factory signature to the dictionary
            //                factoryMethods[tr.Name].Add(myInfo);
            //            }

            //        }
            //    }

            //    //#endregion
            //}

            // Render equals
            sw.WriteLine(CreateEqualityMethod(cls));
            // End class
            sw.WriteLine("}");


            #region Render the imports
            string[] apiImports = { "annotations.*", "datatypes.*", "datatypes.generic.*", "interfaces.IGraphable" },
                jImports = { "java.lang.*", "java.util.*" };
            foreach (var import in apiImports)
                tw.WriteLine("import {0}.{1};", apiNs, import);
            foreach (var import in jImports)
                tw.WriteLine("import {0};", import);
            foreach (var import in s_imports)
            {
                if (!import.EndsWith(String.Format(".{0}", Util.Util.PascalCase(f.Name)))) 
                    tw.WriteLine("import {0};", import);
            }

            tw.WriteLine(sw.ToString());
            #endregion

            if (cls.ContainerName == "RIM" && String.Format("{0}.rim.{1}", ownerPackage, Util.Util.PascalCase(cls.Name)) != RimbaJavaRenderer.RootClass && !RimbaJavaRenderer.GenerateRim)
                throw new NotSupportedException("RIM Elements will not be rendered");

        }
Ejemplo n.º 8
0
        private void ProcessTypeParameters(List<ParameterModel> parms, TypeReference baseRef, MohawkCollege.EHR.gpmr.COR.Interaction ownerInteraction)
        {
            if (parms != null && baseRef.Class != null && baseRef.Class.TypeParameters != null && parms.Count != baseRef.Class.TypeParameters.Count)
                Trace.WriteLine(
                    string.Format("The argument message '{0}.{1}' requires {2} parameter messages however interaction '{3}' only specifies {4}",
                    baseRef.Class.ContainerName, baseRef.Class.Name, baseRef.Class.TypeParameters.Count, ownerInteraction.Name, parms.Count)
                    , "warn");
            else if (parms == null || parms.Count == 0) return; // Check for null

            // Setup the parameters
            foreach (ParameterModel p in parms)
            {
                // Check if the parameter model exists
                if (!ClassRepository.ContainsKey(p.ToString(MifCompiler.NAME_FORMAT)))
                    PackageParser.Parse(p.ToString(MifCompiler.NAME_FORMAT), repository, ClassRepository); // Process the package if it doesn't

                // Check again, if this fails all hell breaks loose
                var model = (ClassRepository[p.ToString(MifCompiler.NAME_FORMAT)] as MohawkCollege.EHR.gpmr.COR.SubSystem);
                if (model == null)
                {
                    System.Diagnostics.Trace.WriteLine(string.Format("Could not find the parameter model '{0}'",
                        p.ToString(MifCompiler.NAME_FORMAT)), "error");
                    return;
                }
                else if (model.EntryPoint.Count == 0)
                {
                    System.Diagnostics.Trace.WriteLine(string.Format("Parameter model '{0}' must have an entry point",
                        p.ToString(MifCompiler.NAME_FORMAT)), "error");
                    return;
                }
                else if (model.EntryPoint.Count != 1)
                {
                    System.Diagnostics.Trace.WriteLine(string.Format("Ambiguous entry point for parameter model '{0}'",
                        p.ToString(MifCompiler.NAME_FORMAT)), "error");
                    return;
                }

                // Entry class for p
                TypeReference parmRef = model.EntryPoint[0].CreateTypeReference();

                // Find any reference and set an alternate traversal name for that property
                if (p.Specialization.Count == 0)
                    AppendTraversalName(baseRef, p.ParameterName, p.TraversalName, parmRef, ownerInteraction, new Stack<string>());
                else
                    ProcessSpecializations(p, p.Specialization, baseRef, ownerInteraction, null);

                // Process Children
                ProcessTypeParameters(p.ParameterModel, parmRef, ownerInteraction);

                // Assign for tr as a parameter reference
                try
                {
                    baseRef.AddGenericSupplier(p.ParameterName, parmRef);
                }
                catch (ArgumentException e) // This is thrown when there are more than one supplier binding
                {
                    // Was more than one specified
                    if (baseRef.GenericSupplier.Exists(o => (o as TypeParameter).ParameterName == p.ParameterName)) 
                    {
                        //baseRef.GenericSupplier.RemoveAll(o => (o as TypeParameter).ParameterName == p.ParameterName);  // remove the existing type reference
                        // Add the generic supplier manually for the new type
                        baseRef.AddGenericSupplier(p.ParameterName, parmRef, false);
                        Trace.WriteLine(String.Format("Generic supplier {0} has been specified more than once, will use base object in it's place", p.ParameterName), "warn");
                    }
                }
                catch (Exception e)
                {
                    // JF - Some UV models attempt to bind to classes that don't support binding
                    if (baseRef.Class.TypeParameters == null)
                    {
                        System.Diagnostics.Trace.WriteLine(String.Format("{0} can't force bind because the target class has not template parameters", e.Message), "error");
                        if (MifCompiler.hostContext.Mode == Pipeline.OperationModeType.Quirks)
                            System.Diagnostics.Trace.WriteLine(String.Format("{0} will ignore this binding in order to continue. This interaction will effectively be useless", ownerInteraction.Name));
                        else
                            throw new InvalidOperationException(String.Format("Cannot bind parameter '{0}' to class '{1}' because '{1}' does not support templates", parmRef.Name, baseRef.Name));
                    }
                    else
                    {
                        System.Diagnostics.Trace.WriteLine(String.Format("{0} will try force binding", e.Message), "error");
                        foreach (var t in baseRef.Class.TypeParameters)
                            if (baseRef.GenericSupplier.Find(o => o.Name.Equals(t.ParameterName)) == null)
                            {
                                baseRef.AddGenericSupplier(t.ParameterName, parmRef);
                                System.Diagnostics.Trace.WriteLine(String.Format("Bound {0} to {1} in {2}", parmRef, t.ParameterName, baseRef), "warn");
                                break;
                            }
                    }
                }
                
            }
        }
Ejemplo n.º 9
0
        private void ProcessSpecializations(ParameterModel p, List<AssociationEndSpecialization> list, TypeReference baseRef, MohawkCollege.EHR.gpmr.COR.Interaction interactionModel, TypeReference hint)
        {
            TypeReference parmRef = null;
            foreach (var specialization in list) // This shouldn't ever be done ... ever, but this is v3 land
            {
                Class specClass = (ClassRepository[p.ToString(MifCompiler.NAME_FORMAT)] as MohawkCollege.EHR.gpmr.COR.SubSystem).OwnedClasses.Find(c => c.Name == specialization.ClassName);
                if(specClass == null && hint != null)
                {
                    // Find all sub-classes and see if the hint contains them
                    TypeReference specClassRef = hint.Class.SpecializedBy.Find(o => o.Class.Name == specialization.ClassName);
                    // Make the reference a concreate COR class 
                    if (specClassRef != null) specClass = specClassRef.Class;
                }
                if (specClass == null) // Do a CMET lookup
                {
                    MohawkCollege.EHR.gpmr.COR.Feature cmetFeature = null;
                    if (ClassRepository.TryGetValue(specialization.ClassName, out cmetFeature))
                        specClass = (cmetFeature as CommonTypeReference).Class.Class;
                    else
                    {
                        System.Diagnostics.Trace.WriteLine(string.Format("Can't find specialization '{0}' for parameter '{1}' this traversal will be ignored.", specialization.ClassName, p.ParameterName), "warn");
                        continue;
                    }
                }

                parmRef = specClass.CreateTypeReference();
                // Append the traversal name
                AppendTraversalName(baseRef, p.ParameterName, specialization.TraversalName, parmRef, interactionModel, new Stack<string>());
                if (specialization.Specialization.Count > 0)
                    ProcessSpecializations(p, specialization.Specialization, baseRef, interactionModel, parmRef);
            }
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Parse a COR state that belongs to a state machine from a MIF 2.0 state 
        /// </summary>
        private static MohawkCollege.EHR.gpmr.COR.State Parse(MohawkCollege.EHR.HL7v3.MIF.MIF20.State st)
        {
            State retVal = new State();

            if(st.Annotations != null)
                retVal.Documentation = DocumentationParser.Parse(st.Annotations.Documentation);
            retVal.Name = st.Name;
            retVal.ParentStateName = st.ParentStateName;
            //retVal.ChildStates = new Dictionary<string, State>();

            return retVal;
        }
Ejemplo n.º 11
0
        private void AppendTraversalName(TypeReference ClassRef, string ParameterName, string TraversalName, TypeReference CaseWhen, MohawkCollege.EHR.gpmr.COR.Interaction InteractionOwner, Stack<String> processStack)
        {
            if (processStack.Contains(ClassRef.ToString()))
                return;

            processStack.Push(ClassRef.ToString());

            // Iterate through each of the class contents
            foreach(ClassContent cc in ClassRef.Class.Content)
                if (cc is Property)
                {
                    // Assign Alternative traversal name if the type of property matches the paramter name 
                    // and the new traversal name is not the same as the old 
                    if ((cc as Property).Type.Name == ParameterName &&
                        TraversalName != cc.Name )
                        (cc as Property).AddTraversalName(TraversalName, CaseWhen, InteractionOwner);
                    else if ((cc as Property).Type.Class != null)
                        AppendTraversalName((cc as Property).Type, ParameterName, TraversalName, CaseWhen, InteractionOwner, processStack);
                }

            if (processStack.Pop() != ClassRef.ToString())
                throw new PipelineExecutionException(MifCompiler.hostContext, Pipeline.PipelineStates.Error, MifCompiler.hostContext.Data,
                    new Exception("Error occurred traversing traversal name to populate parameter"));
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Create a file name 
        /// </summary>
        /// <param name="f">The feature to create a file for</param>
        /// <param name="FilePath">The path of the file</param>
        /// <returns>The full name of the file to create</returns>
        public string CreateFile(MohawkCollege.EHR.gpmr.COR.Feature f, string FilePath)
        {
            string fileName = Util.Util.MakeFriendly(f.Name);

            // Render as
            if (f.Annotations != null && f.Annotations.Exists(o => o is RenderAsAnnotation))
                fileName = Util.Util.MakeFriendly((f.Annotations.Find(o => o is RenderAsAnnotation) as RenderAsAnnotation).RenderName);

            fileName = Path.ChangeExtension(Path.Combine(Path.Combine(FilePath, "Vocabulary"), fileName), ".cs");

            var enu = f as Enumeration;

            if (!String.IsNullOrEmpty(Datatypes.GetBuiltinVocabulary(enu.Name)))
                throw new InvalidOperationException("Enumeration is builtin to core library. Will not render");

            // Is this code system even used?
            if (!m_markedForUse.Exists(o=>o.GetType().Equals(f.GetType()) && o.Name == f.Name))
            {
                if (enu.GetEnumeratedLiterals().Count > RimbaCsRenderer.MaxLiterals)
                    throw new InvalidOperationException(String.Format("Enumeration '{2}' too large, enumeration has {0} literals, maximum allowed is {1}",
                        enu.GetEnumeratedLiterals().Count, RimbaCsRenderer.MaxLiterals, enu.Name));
                else
                    throw new InvalidOperationException("Enumeration is not used, or is an unbound concept domain!");
            }



            // First, if the feature is a value set we will always render it
            if (File.Exists(fileName) && !(f as Enumeration).OwnerRealm.EndsWith(RimbaCsRenderer.prefRealm))
                throw new InvalidOperationException("Enumeration has already been rendered from the preferred realm. Will not render this feature");

            return fileName;
        }
Ejemplo n.º 13
0
        private void CascadeGenerics(MohawkCollege.EHR.gpmr.COR.Class cls, Stack<string> CurrentlyProcessing)
        {
            if (cls == null || CurrentlyProcessing.Contains(cls.Name)) // Something to process and we aren't already processing it
                return;

            // Push on the current class
            CurrentlyProcessing.Push(cls.Name);

            foreach(ClassContent cc in cls.Content)
                if (cc is Property)
                {
                    
                    // Now set the generics of the class to this
                    if ((cc as Property).Type.Class == null) continue; // Base datatype so don't worry
                    
                    CascadeGenerics((cc as Property).Type.Class, CurrentlyProcessing);

                    foreach (TypeParameter p in (cc as Property).Type.Class.TypeParameters ?? new List<TypeParameter>())
                    {
                        cls.AddTypeParameter(p);
                        (cc as Property).Type.AddGenericSupplier(p.ParameterName, p);
                    }
                }

            CurrentlyProcessing.Pop(); // Pop off the current class
        }
Ejemplo n.º 14
0
 //DOC: Documentation Required
 /// <summary>
 /// 
 /// </summary>
 /// <param name="f"></param>
 /// <param name="FilePath"></param>
 /// <returns></returns>
 public string CreateFile(MohawkCollege.EHR.gpmr.COR.Feature f, string FilePath)
 {
     return Path.ChangeExtension(Path.Combine(Path.Combine(FilePath, (f as Class).ContainerName),Util.Util.PascalCase(f.Name)), "cs");
 }
Ejemplo n.º 15
0
        public void Render(String OwnerNs, String apiNs, MohawkCollege.EHR.gpmr.COR.Feature f, System.IO.TextWriter tw)
        {
            m_methodDeclarations = new List<string>();

            StringWriter sw = new StringWriter();
            
            // Make a strong typed reference to class
            Class cls = f as Class;

            #region Usings

            // Validate Usings
            string[] usings = new string[] { "Attributes", "Interfaces", "DataTypes" };
            foreach (string s in usings)
                sw.WriteLine("using {1}.{0};", s, apiNs);

            if (f.MemberOf.Find(o => o is Enumeration) != null)
                sw.WriteLine("using {0}.Vocabulary;", OwnerNs);


            #endregion

            #region Render

            sw.WriteLine("namespace {1}.{0} {{", cls.ContainerName, OwnerNs); // Start of Namespace

            // document the namespace if not already done
            if (!nsDocGenerated.Contains(cls.ContainerName))
            {
                if (cls.ContainerPackage.Documentation != null)
                {
                    sw.WriteLine("\t/// <summary>{0}</summary>", cls.ContainerPackage.BusinessName);
                    sw.WriteLine("\tinternal class NamespaceDoc { }");
                }
                nsDocGenerated.Add(cls.ContainerName);
            }

            // Documentation
            if (DocumentationRenderer.Render(cls.Documentation, 1).Length == 0)
                sw.WriteLine("\t/// <summary>{0}</summary>", cls.BusinessName == null ? "No documentation found" : cls.BusinessName.Replace("\r","").Replace("\n","").Replace("&","&amp;") );
            else
                sw.Write(DocumentationRenderer.Render(cls.Documentation, 1));

            #region Start Class
            // Structure attribute for the class
            sw.WriteLine("\t" + CreateStructureAttribute(cls));

            string genericString = "";
            foreach (TypeParameter tp in cls.TypeParameters ?? new List<TypeParameter>())
                genericString += tp + ",";
            
            // Open Class 
            sw.WriteLine("\t[System.ComponentModel.Description(\"{0}\")]", cls.BusinessName != null ? cls.BusinessName.Replace("\n", "").Replace("\r", "") : cls.Name);
            sw.WriteLine("\t#if !WINDOWS_PHONE");
            sw.WriteLine("\t[Serializable]");
            sw.WriteLine("\t#endif");
            sw.WriteLine("\t[System.CodeDom.Compiler.GeneratedCode(\"gpmr\",\"{0}\")]", Assembly.GetEntryAssembly().GetName().Version.ToString());

            // JF-19/04/10 : Used to support mapping back to RIM
            foreach (var realization in cls.Realizations ?? new List<TypeReference>())
            {
                sw.Write("\t[Realization(Name = \"{0}\"", realization.Class.Name);
                if (RimbaCsRenderer.GenerateRim)
                    sw.Write(", OwnerClass = typeof({0}.{1})", OwnerNs, realization.Name);
                sw.WriteLine(")]");
            }

            sw.Write("\tpublic {0}class {1}{2} : {3}.{4}, IGraphable, IEquatable<{1}{2}>\r\n#if !WINDOWS_PHONE\r\n, ICloneable\r\n#endif\r\n", 
                cls.IsAbstract ? "abstract " : "", Util.Util.PascalCase(cls.Name), genericString.Length == 0 ? "" : "<" + genericString.Substring(0, genericString.Length - 1) + ">",
                "RIM." + Util.Util.PascalCase(cls.Name) == RimbaCsRenderer.RootClass ? "System" : OwnerNs, "RIM." + Util.Util.PascalCase(cls.Name) == RimbaCsRenderer.RootClass ? "Object" : cls.BaseClass != null ? String.Format("{0}.{1}", cls.BaseClass.Class.ContainerName, Util.Util.PascalCase(cls.BaseClass.Class.Name)) : RimbaCsRenderer.RootClass); // Start of class structure

            // Determine which interfaces this class implements
            List<String> interfaces = MohawkCollege.EHR.gpmr.Pipeline.Renderer.RimbaCS.HeuristicEngine.Interfaces.MapInterfaces(cls);
            foreach (string s in interfaces)
                sw.Write(", {0}", s);
            
            sw.WriteLine("\r\n\t{");
            #endregion

            #region Object Reference Id (used for hashing)

            sw.WriteLine("\t\t// Object reference identifier");
            sw.WriteLine("\t\tprivate readonly object m_objectRefId = new object();");

            #endregion

            #region Properties

            int propertySort = 0;

            // Get the content up the tree

            List<ClassContent> content = new List<ClassContent>(cls.Content);
            var c = cls.BaseClass;
            while (c != null && c.Class != null)
            {
                foreach (var itm in c.Class.Content)
                {
                    if (content.Exists(o => o.Name == itm.Name)) continue;
                    var addItm = itm.Clone() as ClassContent;
                    addItm.Container = cls; // set the container
                    content.Add(addItm);
                }
                c = c.Class.BaseClass;
            }
            // Sort
            content.Sort(new ClassContent.Comparator());

            foreach (ClassContent cc in content)
                sw.WriteLine(CreateProperty(cc, OwnerNs, propertySort++));

            #endregion

            if(!cls.IsAbstract)
            {
                #region Constructors

                sw.WriteLine("\t\t/// <summary> Default CTOR </summary>");
                sw.WriteLine("\t\tpublic {0}() : base() {{ }}\r\n", Util.Util.PascalCase(cls.Name));

                Dictionary<String, String[]> ctors = CreateFactoryMethod(cls.CreateTypeReference(), "this");

                // Write CTOR
                List<String> wroteParms = new List<string>(); // Keep track of the parameters used
                foreach (KeyValuePair<String, String[]> kv in ctors)
                {
                    if (kv.Value[0].Length > 0 && !wroteParms.Contains(kv.Value[0]))
                    {
                        wroteParms.Add(kv.Value[0]);
                        sw.WriteLine("\t\t/// <summary>\r\n\t\t/// CTOR for all {0} elements\r\n\t\t/// </summary>", kv.Key);
                        sw.WriteLine(kv.Value[2]);
                        sw.WriteLine("\t\tpublic {0}({1}) : base() {{ \r\n\t\t{2}\t\t}}", Util.Util.PascalCase(cls.Name), kv.Value[0].Substring(0, kv.Value[0].Length - 1), kv.Value[1]);
                    }
                }
                
                #endregion

                //#region Generate Collapsed Constructor

                //sw.WriteLine(CreateCollapsedConstructor(cls, OwnerNs));

                //#endregion
            }

            // Is this an emtpy class that facilitates a choice?
            if (cls.SpecializedBy != null && cls.SpecializedBy.Count > 0 &&
                cls.IsAbstract)
            {
                #region Generate creator methods for each of the children

                foreach (TypeReference tr in CascadeSpecializers(cls.SpecializedBy))
                {

                    if (tr.Class == null || tr.Class.ContainerName == "RIM" && !RimbaCsRenderer.GenerateRim || 
                        tr.Class.IsAbstract)
                        continue;

                    Class child = tr.Class;

                    // Is method
                    sw.WriteLine("\t\t///<summary>Returns true if this abstract class instance is an instance of <see cref=\"T:{0}.{1}\"/></summary>\r\n\t\tpublic bool Is{2}() {{ ", OwnerNs, tr.Name, tr.Name.Replace(".",""));
                    sw.WriteLine("\t\t\treturn this is {0}.{1};", OwnerNs, tr.Name);
                    sw.WriteLine("\t\t}");

                    // Create factory for the child
                    Dictionary<String, String[]> ctors = CreateFactoryMethod(tr, "retVal");
                    // Write factory
                    foreach (var kv in ctors)
                    {

                        string methodSignature = String.Format("{1}.{0}.{2}.Create{3}", cls.ContainerName, OwnerNs, Util.Util.PascalCase(cls.Name), Util.Util.PascalCase(child.Name)),
                            publicName = methodSignature;
                        
                        // Regex for extracting the parameter type rather than the type/name
                        Regex parmRegex = new Regex(@"(([\w<>,.]*)\s(\w*)),?\s?");
                        MatchCollection parmMatches = parmRegex.Matches(kv.Value[0]);
                        foreach (Match match in parmMatches)
                            methodSignature += match.Groups[1].Value.Substring(0, match.Groups[1].Value.IndexOf(" "));


                        // JF: Added to protected against rendering the same factory method
                        if (m_methodDeclarations.Contains(methodSignature))
                            continue;
                        m_methodDeclarations.Add(methodSignature);

                        // Render if there is even any content
                        if (kv.Value[0].Length > 0)
                        {
                            sw.Write(DocumentationRenderer.Render(child.Documentation, 2));
                            sw.WriteLine("\t\t///<summary>Create a new instance of <see cref=\"T:{0}.{1}\"/></summary>\r\n{4}\t\tpublic static {0}.{1} Create{2}({3}) {{ ", OwnerNs, tr.Name, Util.Util.PascalCase(child.Name), kv.Value[0].Substring(0, kv.Value[0].Length - 1), kv.Value[2]);
                            sw.WriteLine("\t\t\t{0}.{1} retVal = new {0}.{1}();", OwnerNs, tr.Name);
                            sw.WriteLine("\t\t\t{0}", kv.Value[1]);
                            sw.WriteLine("\t\t\treturn retVal;");
                            sw.WriteLine("\t\t}");

                            

                            if (!factoryMethods.ContainsKey(tr.Name))
                                factoryMethods.Add(tr.Name, new List<FactoryMethodInfo>());

                            FactoryMethodInfo myInfo = new FactoryMethodInfo(publicName, kv.Value[2], methodSignature);


                                //Match the regular expression below and capture its match into backreference number 1 «(([\w<>,]*?)\s(\w*),?\s?)»
                                //Match the regular expression below and capture its match into backreference number 2 «([\w<>,]*?)»
                                //Match a single character present in the list below «[\w<>,]*?»
                                //Between zero and unlimited times, as few times as possible, expanding as needed (lazy) «*?»
                                //A word character (letters, digits, etc.) «\w»
                                //One of the characters “<>,” «<>,»
                                //Match a single character that is a “whitespace character” (spaces, tabs, line breaks, etc.) «\s»
                                //Match the regular expression below and capture its match into backreference number 3 «(\w*)»
                                //Match a single character that is a “word character” (letters, digits, etc.) «\w*»
                                //Between zero and unlimited times, as many times as possible, giving back as needed (greedy) «*»
                                //Match the character “,” literally «,?»
                                //Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
                                //Match a single character that is a “whitespace character” (spaces, tabs, line breaks, etc.) «\s?»
                                //Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
                            foreach (Match match in parmMatches)
                                myInfo.parameters.Add(match.Groups[1].Value);

                            // ADd the factory signature to the dictionary
                            factoryMethods[tr.Name].Add(myInfo);
                        }

                    }
                }

                #endregion
            }

            #region Validate Function
            //if (!cls.IsAbstract)
                sw.WriteLine(CreateValidateFunction(cls));

            sw.WriteLine(CreateEqualityMethod(cls));
            #endregion

            #region Clone Function

            sw.WriteLine("\t\tpublic new object Clone() { return this.MemberwiseClone(); }");

            #endregion
            sw.WriteLine("\t}"); // End of Class
            sw.WriteLine("}"); // End of Namespace

            #endregion

            if (cls.ContainerName == "RIM" && ("RIM." + Util.Util.PascalCase(cls.Name) == RimbaCsRenderer.RootClass || RimbaCsRenderer.GenerateRim) ||
                cls.ContainerName != "RIM")
                tw.Write(sw); // Write string writer
            else
                throw new NotSupportedException("RIM Elements will not be rendered");

        }
Ejemplo n.º 16
0
        /// <summary>
        /// Perform optimizations on <paramref name="source"/>
        /// </summary>
        /// <param name="source">The class repository to optimize</param>
        /// <returns>The optimized class repository</returns>
        public MohawkCollege.EHR.gpmr.COR.ClassRepository Optimize(MohawkCollege.EHR.gpmr.COR.ClassRepository source, CombineLog currentLog)
        {
            MohawkCollege.EHR.gpmr.COR.ClassRepository optimizedClassRepository = new MohawkCollege.EHR.gpmr.COR.ClassRepository();

            // Copy to the optimized class library, two stop process because dictionaries are wierd
            // First pass, copy the destination stuff
            foreach (var featurePair in source)
            {
                if (currentLog.CombineOps.Exists(o => o.Destination == featurePair.Key))
                {
                    optimizedClassRepository.Add(featurePair.Key, featurePair.Value); // Attempt to fix a bug where the memberOf does not get updated on child content
                    SetMemberOf(optimizedClassRepository[featurePair.Key], optimizedClassRepository);
                }
            }
            // Second pass, copy the collapsed stuff
            foreach (var featurePair in source)
            {
                if (!currentLog.CombineOps.Exists(o => o.Destination == featurePair.Key))
                {
                    optimizedClassRepository.Add(featurePair.Key, featurePair.Value); // Attempt to fix a bug where the memberOf does not get updated on child content
                    SetMemberOf(optimizedClassRepository[featurePair.Key], optimizedClassRepository);
                }
            }

            currentLog.CombineOps.Clear();
            
            // Scan for optimizers
            Dictionary<String, ICorOptimizer> optimizers = new Dictionary<string,ICorOptimizer>();
            var optimizerTypes = from type in this.GetType().Assembly.GetTypes()
                                 where type.GetInterface("MohawkCollege.EHR.gpmr.Pipeline.Triggers.CorCollapser.ICorOptimizer") != null
                                 select type;

            // Add the optimizers
            foreach (var type in optimizerTypes)
            {
                ICorOptimizer optimizer = (ICorOptimizer)type.GetConstructor(Type.EmptyTypes).Invoke(null);
                optimizer.Repository = optimizedClassRepository;
                optimizers.Add(optimizer.HandlesType.ToString(), optimizer);
            }

            // Now process the class repository
            foreach (var featurePair in source)
            {
                ICorOptimizer handler = null;
                Feature f = null;
                if (optimizers.TryGetValue(featurePair.Value.GetType().ToString(), out handler) && 
                    optimizedClassRepository.TryGetValue(featurePair.Key, out f))
                {
                    System.Diagnostics.Trace.WriteLine(String.Format("Processing '{0}'...", featurePair.Key), "debug");
                    Feature optimizedFeature = handler.Optimize(optimizedClassRepository[featurePair.Key], currentLog);
                }
                else if(handler == null)
                    System.Diagnostics.Trace.WriteLine(String.Format("Can't find handler for '{0}', no optimizations will be performed on '{1}'...", featurePair.Value.GetType().ToString(), featurePair.Key), "warn");

            }

            // Get rid of empty sub-systems
            var subSystems = from subSys in source
                             where subSys.Value is SubSystem
                             select subSys.Value as SubSystem;
            foreach (var subSystem in subSystems)
            {
                SubSystem ss = optimizedClassRepository[subSystem.Name] as SubSystem;
                if (ss.OwnedClasses.Count == 0)
                {
                    System.Diagnostics.Trace.WriteLine(String.Format("Removing empty sub-system '{0}'...", ss.Name), "error");
                    optimizedClassRepository.Remove(ss.Name);
                }
            }

            return optimizedClassRepository;
        }
Ejemplo n.º 17
0
 /// TODO: Explanation of parameters missing: OwnerNS, apiNs, f and tw
 ///       Summary explanation needed
 public void Render(String OwnerNS, String apiNs, MohawkCollege.EHR.gpmr.COR.Feature f, System.IO.TextWriter tw)
 {
     return; // no file is created
 }
Ejemplo n.º 18
0
 public MohawkCollege.EHR.gpmr.COR.ClassRepository CompileMif(MohawkCollege.EHR.HL7v3.MIF.MIF20.Repository.PackageRepository pkr)
 {
     ClassRepository retVal = new ClassRepository();
     CompileMif(pkr, retVal);
     return retVal;
 }
Ejemplo n.º 19
0
 internal static MohawkCollege.EHR.gpmr.COR.Documentation Parse(MohawkCollege.EHR.HL7v3.MIF.MIF20.Documentation annot)
 {
     return ParseAddPrefix(String.Empty, annot);
 }
Ejemplo n.º 20
0
        /// <summary>
        /// Optimize the <paramref name="feature"/>
        /// </summary>
        public MohawkCollege.EHR.gpmr.COR.Feature Optimize(MohawkCollege.EHR.gpmr.COR.Feature f, CombineLog workingLog)
        {
            string qualifiedName = String.Format("{0}.{1}", (f as Class).ContainerName, f.Name);
            // Garbage bin
            List<String> classGarbageBin = new List<string>();
            List<ClassContent> contentGarbageBin = new List<ClassContent>();

            // Still valid to process this feature
            if (!Repository.ContainsKey(qualifiedName)) 
                return null; // Can't process non-existant class

            // First determine if a class that is identical to this already exists
            FeatureComparer comparer = new FeatureComparer();
            var matchingFeatures = from kv in Repository
                                            where comparer.Compare(kv.Value, f) == 0
                                            select kv.Value;

            CombineInfo currentCombinationLog = new CombineInfo();

            // Find matching features in each of the sub-systems
            if (matchingFeatures.Count() > 1 && CorCollapserPipelineTrigger.combine == true)
            {
                System.Diagnostics.Trace.WriteLine(String.Format("{0} other classes can be represented by this class", matchingFeatures.Count()), "debug");
                currentCombinationLog.Destination = qualifiedName;

                foreach (var s in matchingFeatures)
                {
                    string qName = String.Format("{0}.{1}", (s as Class).ContainerName, s.Name);
                    if (qName != qualifiedName)
                    {
                        
                        System.Diagnostics.Trace.WriteLine(String.Format("\tReplaces '{0}'", qName), "debug");
                        currentCombinationLog.Class.Add(qName);

                        // Copy alternate traversal data
                        foreach (ClassContent cc in (s as Class).Content)
                            if (cc is Property && (cc as Property).AlternateTraversalNames != null)
                            {
                                if (((f as Class).Content.Find(o => o.Name == cc.Name) as Property).AlternateTraversalNames == null)
                                    ((f as Class).Content.Find(o => o.Name == cc.Name) as Property).AlternateTraversalNames = new List<Property.AlternateTraversalData>();
                                ((f as Class).Content.Find(o => o.Name == cc.Name) as Property).AlternateTraversalNames.AddRange((cc as Property).AlternateTraversalNames);
                            }
                        // Replace referneces
                        ReplaceReferences(s as Class, f as Class);

                        // Add an annotation
                        f.Annotations.Add(new CodeCombineAnnotation((s as Class).CreateTypeReference()));

                        // Remove this class (Add it to the garbage bin)
                        classGarbageBin.Add(qName);
                    }
                }
                workingLog.CombineOps.Add(currentCombinationLog);
            }

            // Now collapse members
            if (CorCollapserPipelineTrigger.collapse)
            {
                for(int i = 0; i < (f as Class).Content.Count; i++)
                {
                    ClassContent cc = (f as Class).Content[i];
                    // Determine if it is a candidate for collapsing needless complexity
                    if (IsCandidateForMeaninglessComplexityCollapse(cc))
                    {
                        while (IsCandidateForMeaninglessComplexityCollapse(cc))
                        {
                            System.Diagnostics.Trace.WriteLine(string.Format("\tCollapsing '{0}'", cc.Name), "debug");
                            CollapseMemberType(cc, f as Class);
                        }
                    }
                    // Determine if it is a candidate for collapsing the entire type
                    else if (IsCandidateForTypeCollapse(cc))
                    {
                        System.Diagnostics.Trace.WriteLine(string.Format("\tCollapsing '{0}'", cc.Name), "debug");
                        CopyMembers((cc as Property).Type, f as Class, cc);
                        contentGarbageBin.Add(cc);
                    }
                }

                // Clean up garbage bin
                (f as Class).Content.RemoveAll(a => contentGarbageBin.Contains(a));
                (f as Class).Content.Sort(new ClassContent.Comparator());
            }
            
            // Clean the garbage bin
            foreach (string s in classGarbageBin)
                Repository.Remove(s);

            return null;
        }