/// <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; }
/// <summary> /// Count references of the type in the specified class content /// </summary> private int CountReferences(ClassContent cc, TypeReference tr) { int retVal = 0; FeatureComparer fc = new FeatureComparer(); if (cc is Property && fc.CompareTypeReference((cc as Property).Type, tr) == 0) retVal++; else if (cc is Choice) foreach (ClassContent scc in (cc as Choice).Content) retVal += CountReferences(scc, tr); return retVal; }