Example #1
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);
        }
        /// <summary>
        /// Fires when the host context has changed
        /// </summary>
        /// <param name="Context">The pipeline that is changing state</param>
        /// <param name="OldState">The old state</param>
        /// <param name="NewState">The new state</param>
        void hostContext_StateChanged(Pipeline Context, Pipeline.PipelineStates OldState, Pipeline.PipelineStates NewState)
        {
            switch (NewState)
            {
                case Pipeline.PipelineStates.SourceLoaded:

                    Dictionary<String, StringCollection> parameters = hostContext.Data["CommandParameters"] as Dictionary<String, StringCollection>;
                    StringCollection tCollection = null;
                    if (parameters.TryGetValue("optimize", out tCollection))
                        enabled = Convert.ToBoolean(tCollection[0]);
                    // Collection
                    if (parameters.TryGetValue("collapse", out tCollection))
                        collapse = Convert.ToBoolean(tCollection[0]);
                    // Combination
                    if (parameters.TryGetValue("combine", out tCollection))
                        combine = Convert.ToBoolean(tCollection[0]);
                    if (parameters.TryGetValue("collapse-ignore-fixed", out tCollection))
                        collapseIgnoreFixed = Convert.ToBoolean(tCollection[0]);
                    if (parameters.TryGetValue("collapse-useless-name", out tCollection))
                        foreach(String s in tCollection)
                            uselessWords.Add(s);
                    if (parameters.TryGetValue("collapse-important-name", out tCollection))
                        foreach (String s in tCollection)
                            importantWords.Add(s);
                    if (parameters.TryGetValue("collapse-adv-naming", out tCollection))
                        collapseSpecialNaming = Convert.ToBoolean(tCollection[0]);
                    if (parameters.TryGetValue("combine-replay", out tCollection))
                        logFile = tCollection[0];
                    // Collapse ignore
                    if (!parameters.TryGetValue("collapse-ignore", out collapseIgnore) && collapse)
                        throw new InvalidOperationException("If --collapse is specified, then the --collapse-ignore must be specified");
                    break;
                case Pipeline.PipelineStates.Compiled:
                    if (!enabled) return;
                    // Optimize the COR repository
                    System.Diagnostics.Trace.WriteLine("Optimizing COR Repository...", "information");
                    ClassRepository classRep = hostContext.Data["SourceCR"] as ClassRepository;
                    ClassRepositoryOptimizer optimizer = new ClassRepositoryOptimizer();

                    // Load the replay log if possible
                    var combineLog = new CombineLog();
                    if (!String.IsNullOrEmpty(logFile) && File.Exists(logFile))
                        combineLog = CombineLog.Load(logFile);

                    ClassRepository optimizedRepository = optimizer.Optimize(classRep, combineLog);

                    // Save the replay log
                    if (!String.IsNullOrEmpty(logFile))
                        combineLog.Save(logFile);

                    System.Diagnostics.Trace.WriteLine(string.Format("Optimization resulted in {0:#,##0} fewer features ({1:#0}% reduction)", classRep.Count - optimizedRepository.Count,
                        (1 - ((float)optimizedRepository.Count / classRep.Count)) * 100), "debug");
                    hostContext.Data["SourceCR"] = optimizedRepository;
                    break;
            }

        }
        /// <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;
        }
        /// <summary>
        /// Fires when the host context has changed
        /// </summary>
        /// <param name="Context">The pipeline that is changing state</param>
        /// <param name="OldState">The old state</param>
        /// <param name="NewState">The new state</param>
        void hostContext_StateChanged(Pipeline Context, Pipeline.PipelineStates OldState, Pipeline.PipelineStates NewState)
        {
            switch (NewState)
            {
            case Pipeline.PipelineStates.SourceLoaded:

                Dictionary <String, StringCollection> parameters = hostContext.Data["CommandParameters"] as Dictionary <String, StringCollection>;
                StringCollection tCollection = null;
                if (parameters.TryGetValue("optimize", out tCollection))
                {
                    enabled = Convert.ToBoolean(tCollection[0]);
                }
                // Collection
                if (parameters.TryGetValue("collapse", out tCollection))
                {
                    collapse = Convert.ToBoolean(tCollection[0]);
                }
                // Combination
                if (parameters.TryGetValue("combine", out tCollection))
                {
                    combine = Convert.ToBoolean(tCollection[0]);
                }
                if (parameters.TryGetValue("collapse-ignore-fixed", out tCollection))
                {
                    collapseIgnoreFixed = Convert.ToBoolean(tCollection[0]);
                }
                if (parameters.TryGetValue("collapse-useless-name", out tCollection))
                {
                    foreach (String s in tCollection)
                    {
                        uselessWords.Add(s);
                    }
                }
                if (parameters.TryGetValue("collapse-important-name", out tCollection))
                {
                    foreach (String s in tCollection)
                    {
                        importantWords.Add(s);
                    }
                }
                if (parameters.TryGetValue("collapse-adv-naming", out tCollection))
                {
                    collapseSpecialNaming = Convert.ToBoolean(tCollection[0]);
                }
                if (parameters.TryGetValue("combine-replay", out tCollection))
                {
                    logFile = tCollection[0];
                }
                // Collapse ignore
                if (!parameters.TryGetValue("collapse-ignore", out collapseIgnore) && collapse)
                {
                    throw new InvalidOperationException("If --collapse is specified, then the --collapse-ignore must be specified");
                }
                break;

            case Pipeline.PipelineStates.Compiled:
                if (!enabled)
                {
                    return;
                }
                // Optimize the COR repository
                System.Diagnostics.Trace.WriteLine("Optimizing COR Repository...", "information");
                ClassRepository          classRep  = hostContext.Data["SourceCR"] as ClassRepository;
                ClassRepositoryOptimizer optimizer = new ClassRepositoryOptimizer();

                // Load the replay log if possible
                var combineLog = new CombineLog();
                if (!String.IsNullOrEmpty(logFile) && File.Exists(logFile))
                {
                    combineLog = CombineLog.Load(logFile);
                }

                ClassRepository optimizedRepository = optimizer.Optimize(classRep, combineLog);

                // Save the replay log
                if (!String.IsNullOrEmpty(logFile))
                {
                    combineLog.Save(logFile);
                }

                System.Diagnostics.Trace.WriteLine(string.Format("Optimization resulted in {0:#,##0} fewer features ({1:#0}% reduction)", classRep.Count - optimizedRepository.Count,
                                                                 (1 - ((float)optimizedRepository.Count / classRep.Count)) * 100), "debug");
                hostContext.Data["SourceCR"] = optimizedRepository;
                break;
            }
        }
        /// <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);
        }
Example #6
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;
        }