Exemple #1
0
        /// <summary>
        /// Gets a new instance of an elaborator based on a given context.
        /// </summary>
        /// <param name="subject">Given context</param>
        /// <param name="logger">Logger which can be used to log messages.</param>
        /// <returns>A new instance of a context aware elaborator.</returns>
        /// <exception cref="ArgumentNullException">If subject or logger null.</exception>
        /// <exception cref="NotSupportedException">If subject does not have an associated elaborator class.</exception>
        public static Elaborator GetElaborator(MgaModel subject, CyPhyGUIs.GMELogger logger, bool UnrollConnectors)
        {
            if (subject == null)
            {
                throw new ArgumentNullException("subject");
            }

            if (logger == null)
            {
                throw new ArgumentNullException("logger");
            }

            var        factory    = new CyPhyTypeFactory(subject.Project.RootMeta);
            Elaborator elaborator = null;

            if (subject.MetaBase.MetaRef == factory.TestBenchMeta ||
                subject.MetaBase.MetaRef == factory.CADTestBenchMeta ||
                subject.MetaBase.MetaRef == factory.BlastTestBenchMeta ||
                subject.MetaBase.MetaRef == factory.BallisticTestBenchMeta ||
                subject.MetaBase.MetaRef == factory.CFDTestBenchMeta ||
                subject.MetaBase.MetaRef == factory.KinematicTestBenchMeta ||
                subject.MetaBase.MetaRef == factory.CarTestBenchMeta)
            {
                elaborator = new TestBenchTypeElaborator(subject, UnrollConnectors);
            }
            else if (subject.MetaBase.MetaRef == factory.ComponentAssemblyMeta)
            {
                elaborator = new ComponentAssemblyElaborator(subject, UnrollConnectors);
            }
            else if (subject.MetaBase.MetaRef == factory.DesignContainerMeta)
            {
                elaborator = new DesignContainerElaborator(subject, UnrollConnectors);
            }
            else
            {
                throw new NotSupportedException(string.Format("Not supported context: {0} [{1}]", subject.Name, subject.MetaBase.Name));
            }

            if (subject.IsLibObject)
            {
                throw new NotSupportedException(string.Format("{0} cannot be a library object.", subject.MetaBase.Name));
            }

            elaborator.Logger  = logger;
            elaborator.Factory = factory;
            // TODO: how can we determine this?
            elaborator.IsElaborated = false;

            return(elaborator);
        }
Exemple #2
0
        /// <summary>
        /// Runs the elaborator based on a given context.
        /// </summary>
        /// <param name="currentobj">Current context on which the elaborator should run.</param>
        /// <returns>True if the elaboration was successful</returns>
        /// <exception cref="ElaboratorException">If any problem occurred during elaboration.</exception>
        public bool ElaborateContext(MgaFCO currentobj)
        {
            // initialize traceability map with a new instance
            this.Traceability = new META.MgaTraceability();

            // expose traceability for other interpreters
            this.set_ComponentParameter("traceability", this.Traceability);

            // count all descendant objects before elaboration
            var beforeElaboration = (currentobj as MgaModel).GetDescendantFCOs(currentobj.Project.CreateFilter()).Count;

            // get an elaborator for the current context
            var elaborator = Elaborator.GetElaborator(currentobj as MgaModel, this.Logger, UnrollConnectors);

            // elaborate the entire model starting from the current object
            elaborator.Elaborate();

            // update traceability for this object.
            // TODO: would be nice to have a function on MgaTraceability class like update map and we can pass a dictionary.
            foreach (var item in elaborator.Traceability)
            {
                this.Traceability.AddItem(item.Key, item.Value);
            }

            // statistics about the traceability
            this.Logger.WriteDebug("Traceability map size: {0}", elaborator.Traceability.Count);

            // count all descendant objects after elaboration
            var afterElaboration = (currentobj as MgaModel).GetDescendantFCOs(currentobj.Project.CreateFilter()).Count;

            this.Logger.WriteDebug("Before: {0}, After: {1}", beforeElaboration, afterElaboration);

            // verify traceability
            if (afterElaboration == elaborator.Traceability.Count)
            {
                this.Logger.WriteDebug("Traceability map has traces for all objects within the current context.");
            }
            else
            {
                this.Logger.WriteWarning("Traceability map does not have traces for all objects. {0} are missing in the map.", elaborator.Traceability.Count - afterElaboration);
            }

            return(true);
        }
        /// <summary>
        /// Elaborates the give test bench.
        /// </summary>
        public override void Elaborate()
        {
            // gets all objects within the test bench in any depth.
            MgaFilter filter     = this.Subject.Project.CreateFilter();
            var       allObjects = this.Subject.GetDescendantFCOs(filter);

            // list of test injection points in the test bench
            List <MgaReference> tips = new List <MgaReference>();

            foreach (MgaFCO obj in allObjects)
            {
                // add object to traceability
                this.Traceability.Add(obj.ID, obj.ID);

                if (this.Factory.TestInjectionPointsMeta.Contains(obj.MetaBase.MetaRef))
                {
                    // if object is a kind of test injection point
                    if (obj is MgaReference)
                    {
                        // if it is a reference
                        if ((obj as MgaReference).Referred == null)
                        {
                            this.Logger.WriteWarning(string.Format("{0} [{1}] was ignored and skipped, because it points to a null reference.", obj.Name, obj.MetaBase.Name));
                        }
                        else
                        {
                            // has a valid reference which is not null
                            tips.Add(obj as MgaReference);
                        }
                    }
                    else
                    {
                        this.Logger.WriteError(string.Format("{0} [{1}] is not a reference, therefore it was ignored and skipped.", obj.Name, obj.MetaBase.Name));
                    }
                }
            }

            // get the top level system under test object for this test bench
            var tlsut = allObjects.OfType <MgaReference>().FirstOrDefault(x => x.MetaBase.Name == "TopLevelSystemUnderTest");

            // ASSUME we have exactly one

            // make sure it is not null
            if (tlsut == null)
            {
                this.Logger.WriteWarning(string.Format("No top level system under test object in {0} [{1}]", this.Subject.Name, this.Subject.MetaBase.Name));
                this.Logger.WriteWarning("Assumes [{0}] has been elaborated...", this.Subject.MetaBase.Name);
                this.IsElaborated = true;
                return;
            }

            // it has a null reference
            if (tlsut.Referred == null)
            {
                throw new ElaboratorException(string.Format("Top level system under test object in {0} [{1}] is a null reference.", this.Subject.Name, this.Subject.MetaBase.Name));
            }

            // switch the top level system under test to a Component Assembly
            // FIXME: what if it is not a component assembly ???
            string tlsu_referred_id = tlsut.Referred.ID;
            var    ca_tlsut         = this.SwitchReferenceToModel(this.Subject, tlsut, false);

            // delete the reference object.
            tlsut.DestroyObject();

            // component assembly elaborator used to elaborate the Top Level System Under Test object.
            ComponentAssemblyElaborator componentAssemblyElaborator = null;

            // get a Componenet assembly elaborator for the top level system under test object.
            componentAssemblyElaborator = Elaborator.GetElaborator <ComponentAssemblyElaborator>(ca_tlsut, this.Logger, UnrollConnectors);

            // pass our current traceability information
            componentAssemblyElaborator.Traceability   = this.Traceability;
            componentAssemblyElaborator.ComponentGUIDs = this.ComponentGUIDs;

            // elaborate the top level system under test object
            componentAssemblyElaborator.Elaborate();

            // TODO: Elaborate test components

            // get a look up map for all test injection point references
            var map = componentAssemblyElaborator.GetReverseLookupMap(tips.Select(x => x.Referred.ID));

            map[tlsu_referred_id] = new MgaFCO[] { (MgaFCO)ca_tlsut }.ToList();

            // gather all information about test injection points, pretend everything is ok.
            bool success = true;

            foreach (MgaReference tip in tips)
            {
                // get the new targets for this test injection point
                var tipTargets = map[tip.Referred.ID];

                // looking for exactly one target
                if (tipTargets.Count == 0)
                {
                    // no target mark it as failure
                    success = false;
                    this.Logger.WriteFailed("{0} [{1}] --> {2} [{3}] was not found in traceability.", tip.Name, tip.MetaBase.Name, tip.Referred.Name, tip.Referred.MetaBase.Name);
                }
                else if (tipTargets.Count == 1)
                {
                    // exactly one target
                    try
                    {
                        // redirect test injection point to the new target
                        var switcher = new ReferenceSwitcher.ReferenceSwitcherInterpreter();
                        switcher.SwitchReference(tipTargets[0] as IMgaFCO, tip as IMgaReference);
                    }
                    catch (Exception ex)
                    {
                        success = false;

                        // handle failures for this (use case we can lose ports/connections/
                        // what if something is an instance/subtype/readonly etc...
                        this.Logger.WriteFailed("{0} [{1}] --> {2} [{3}] redirecting to --> {4} [{5}]", tip.Name, tip.MetaBase.Name, tip.Referred.Name, tip.Referred.MetaBase.Name, tipTargets[0].Name, tipTargets[0].MetaBase.Name);
                        this.Logger.WriteDebug(ex.ToString());
                    }
                }
                else
                {
                    // tipTarget.Count > 1
                    // more than one possible targets, this case is ambiguous, therefore mark it as failure.
                    success = false;
                    this.Logger.WriteFailed("{0} [{1}] --> {2} [{3}] was found more than once in the system - the choice is ambiguous.", tip.Name, tip.MetaBase.Name, tip.Referred.Name, tip.Referred.MetaBase.Name);
                }
            }

            if (tips.Any())
            {
                if (success)
                {
                    // check if no problems
                    this.Logger.WriteInfo("All test injection points were redirected successfully.");
                }
                else
                {
                    // some problems occured, must raise an exception
                    throw new ElaboratorException("At least one test injection point was not redirected successfully. See log messages above.");
                }
            }

            // if this point is reached, mark it successful.
            this.IsElaborated = true;
        }
Exemple #4
0
        /// <summary>
        /// Elaborates a DesignContainer object.
        /// </summary>
        public override void Elaborate()
        {
            MgaFilter filter = this.Subject.Project.CreateFilter();

            var allObjects = this.Subject.GetDescendantFCOs(filter);

            foreach (MgaFCO obj in allObjects)
            {
                if (obj.IsPrimaryDerived)
                {
                    obj.DetachFromArcheType();
                }
            }

            foreach (MgaFCO obj in allObjects)
            {
                if (this.Traceability.ContainsKey(obj.ID) == false)
                {
                    // add to traceability
                    this.Traceability.Add(obj.ID, obj.ID);
                }

                if (obj is MgaReference)
                {
                    var reference = obj as MgaReference;
                    if (reference.Referred == null)
                    {
                        if (reference.MetaBase.MetaRef == this.Factory.ComponentRefMeta)
                        {
                            this.Logger.WriteWarning(string.Format("Null {0} [{1}] was ignored and skipped.", reference.Name, reference.MetaBase.Name));
                        }

                        continue;
                    }

                    var referred = reference.Referred;

                    MgaObject parent = null;
                    GME.MGA.Meta.objtype_enum type;
                    reference.GetParent(out parent, out type);

                    if (IsConfigurationType(parent))
                    {
                        continue;
                    }
                    if (parent.MetaBase.MetaRef == Factory.DecisionGroupMeta || parent.MetaBase.MetaRef == Factory.VisualConstraintMeta ||
                        parent.MetaBase.MetaRef == Factory.And_operatorMeta || parent.MetaBase.MetaRef == Factory.Or_operatorMeta ||
                        parent.MetaBase.MetaRef == Factory.Not_operatorMeta)
                    {
                        // DecisionGroup can hold only ComponentRefs, so we can't do anything with its children (META-3595)
                        continue;
                    }

                    if (referred.MetaBase.MetaRef == this.Factory.ComponentMeta)
                    {
                        var copied = this.SwitchReferenceToModel(parent as MgaModel, reference, true);

                        // delete reference
                        reference.DestroyObject();
                    }
                    else if (referred.MetaBase.MetaRef == this.Factory.ComponentAssemblyMeta)
                    {
                        MgaObject parent2 = parent;
                        GME.MGA.Meta.objtype_enum type2;

                        // worst case this will terminate at the root folder level
                        while (parent2 != null && parent2 is MgaModel)
                        {
                            // FIXME: is this safe? should we compare IDs?
                            if (parent2 == reference.Referred)
                            {
                                string message = string.Format("Circular dependency: {0} --> {1}", parent2.Name, reference.Referred.Name);
                                throw new ElaboratorCircularReferenceException(message);
                            }

                            parent2.GetParent(out parent2, out type2);
                        }

                        if (this.ComponentAssemblyReferences.Any(x => x.ID == reference.Referred.ID))
                        {
                            string message = string.Format("Circular dependency: {0} --> {1}", string.Join(" -> ", this.ComponentAssemblyReferences.Select(x => x.Name)), reference.Referred.Name);
                            throw new ElaboratorCircularReferenceException(message);
                        }

                        var copied = this.SwitchReferenceToModel(parent as MgaModel, reference, false);

                        // prevent circular dependency
                        var innerElaborator = Elaborator.GetElaborator(copied, this.Logger, UnrollConnectors) as ComponentAssemblyElaborator;

                        // use only one map
                        innerElaborator.Traceability     = this.Traceability;
                        innerElaborator.ComponentGUIDs   = this.ComponentGUIDs;
                        innerElaborator.ComponentCopyMap = this.ComponentCopyMap;

                        // hold only one queue
                        foreach (var item in this.ComponentAssemblyReferences)
                        {
                            innerElaborator.ComponentAssemblyReferences.Enqueue(item);
                        }

                        innerElaborator.ComponentAssemblyReferences.Enqueue(reference.Referred);
                        this.InnerElaborators.Add(innerElaborator);
                        innerElaborator.Elaborate();

                        // delete reference
                        reference.DestroyObject();
                    }
                    else if (referred.MetaBase.MetaRef == this.Factory.DesignContainerMeta)
                    {
                        MgaObject parent2 = parent;
                        GME.MGA.Meta.objtype_enum type2;

                        // worst case this will terminate at the root folder level
                        while (parent2 != null && parent2 is MgaModel)
                        {
                            // FIXME: is this safe? should we compare IDs?
                            if (parent2 == reference.Referred)
                            {
                                string message = string.Format("Circular dependency: {0} --> {1}", parent2.Name, reference.Referred.Name);
                                throw new ElaboratorCircularReferenceException(message);
                            }

                            parent2.GetParent(out parent2, out type2);
                        }

                        if (this.DesignSpaceReferences.Any(x => x.ID == reference.Referred.ID))
                        {
                            string message = string.Format("Circular dependency: {0} --> {1}", string.Join(" -> ", this.DesignSpaceReferences.Select(x => x.Name)), reference.Referred.Name);
                            throw new ElaboratorCircularReferenceException(message);
                        }

                        var copied = this.SwitchReferenceToModel(parent as MgaModel, reference, false);

                        var innerElaborator = Elaborator.GetElaborator(copied, this.Logger, UnrollConnectors) as DesignContainerElaborator;

                        // use only one map
                        innerElaborator.Traceability     = this.Traceability;
                        innerElaborator.ComponentGUIDs   = this.ComponentGUIDs;
                        innerElaborator.ComponentCopyMap = this.ComponentCopyMap;

                        // hold only one queue
                        foreach (var item in this.DesignSpaceReferences)
                        {
                            innerElaborator.DesignSpaceReferences.Enqueue(item);
                        }

                        innerElaborator.DesignSpaceReferences.Enqueue(reference.Referred);
                        this.InnerElaborators.Add(innerElaborator);
                        innerElaborator.Elaborate();

                        // delete reference
                        reference.DestroyObject();
                    }
                }
            }
        }
        /// <summary>
        /// Elaborates the given context recursively.
        /// </summary>
        public override void Elaborate()
        {
            SortedDictionary <string, MgaModel> parentsWithDupComponentGuids = new SortedDictionary <string, MgaModel>();
            MgaFilter filter = this.Subject.Project.CreateFilter();

            var allObjects = this.Subject.GetDescendantFCOs(filter);

            foreach (MgaFCO obj in allObjects)
            {
                if (obj.IsPrimaryDerived)
                {
                    obj.DetachFromArcheType();
                }
            }

            foreach (MgaFCO obj in allObjects)
            {
                if (this.Traceability.ContainsKey(obj.ID) == false)
                {
                    // add to traceability
                    this.Traceability.Add(obj.ID, obj.ID);
                }

                if (obj is MgaModel)
                {
                    var model = obj as MgaModel;
                    if (model.MetaBase.MetaRef == this.Factory.ComponentAssemblyMeta)
                    {
                        var managedGuid = model.StrAttrByName["ManagedGUID"];
                        if (string.IsNullOrEmpty(managedGuid) == false)
                        {
                            // copiedObj.StrAttrByName["ManagedGUID"] = managedGuid;
                            // model.RegistryValue[RegistryNameInstanceGuidChain] = model.RegistryValue[RegistryNameInstanceGuidChain] + managedGuid;
                        }
                    }
                }
                else if (obj is MgaReference)
                {
                    var reference = obj as MgaReference;
                    if (reference.Referred == null)
                    {
                        if (reference.MetaBase.MetaRef == this.Factory.ComponentRefMeta)
                        {
                            this.Logger.WriteWarning(string.Format("Null {0} [{1}] was ignored and skipped.", reference.Name, reference.MetaBase.Name));
                        }

                        continue;
                    }

                    var referred = reference.Referred;

                    if (referred.MetaBase.MetaRef == this.Factory.ComponentMeta)
                    {
                        MgaObject parent = null;
                        GME.MGA.Meta.objtype_enum type;
                        reference.GetParent(out parent, out type);

                        var instanceGuid = reference.GetStrAttrByNameDisp("InstanceGUID");
                        if (string.IsNullOrWhiteSpace(instanceGuid))
                        {
                            instanceGuid = new Guid(reference.GetGuidDisp()).ToString("D");
                            reference.SetStrAttrByNameDisp("InstanceGUID", instanceGuid);
                        }
                        if (parent is MgaModel)
                        {
                            instanceGuid = ((MgaModel)parent).RegistryValue[RegistryNameInstanceGuidChain] + instanceGuid;
                            bool dupComponentGuid = !this.ComponentGUIDs.Add(instanceGuid);
                            if (dupComponentGuid)
                            {
                                LogDebug("Duplicate ID " + instanceGuid, reference);
                                parentsWithDupComponentGuids[parent.AbsPath] = parent as MgaModel;
                            }
                        }

                        var copied = this.SwitchReferenceToModel(parent as MgaModel, reference, createInstance: true);

                        // delete reference
                        reference.DestroyObject();
                    }
                    else if (referred.MetaBase.MetaRef == this.Factory.ComponentAssemblyMeta)
                    {
                        MgaObject parent = null;
                        GME.MGA.Meta.objtype_enum type;
                        reference.GetParent(out parent, out type);

                        MgaObject parent2 = parent;
                        GME.MGA.Meta.objtype_enum type2;

                        // worst case this will terminate at the root folder level
                        while (parent2 != null && parent2 is MgaModel)
                        {
                            // FIXME: is this safe? should we compare IDs?
                            if (parent2 == reference.Referred)
                            {
                                string message = string.Format("Circular dependency: {0} --> {1}", parent2.Name, reference.Referred.Name);
                                throw new ElaboratorCircularReferenceException(message);
                            }

                            parent2.GetParent(out parent2, out type2);
                        }

                        if (this.ComponentAssemblyReferences.Any(x => x.ID == reference.Referred.ID))
                        {
                            string message = string.Format("Circular dependency: {0} --> {1}", string.Join(" -> ", this.ComponentAssemblyReferences.Select(x => x.Name)), reference.Referred.Name);
                            throw new ElaboratorCircularReferenceException(message);
                        }

                        var copied = this.SwitchReferenceToModel(parent as MgaModel, reference, false);

                        // prevent circular dependency
                        var innerElaborator = Elaborator.GetElaborator(copied, this.Logger, UnrollConnectors) as ComponentAssemblyElaborator;

                        // use only one map
                        innerElaborator.Traceability     = this.Traceability;
                        innerElaborator.ComponentGUIDs   = this.ComponentGUIDs;
                        innerElaborator.ComponentCopyMap = this.ComponentCopyMap;

                        // hold only one queue
                        foreach (var item in this.ComponentAssemblyReferences)
                        {
                            innerElaborator.ComponentAssemblyReferences.Enqueue(item);
                        }

                        innerElaborator.ComponentAssemblyReferences.Enqueue(reference.Referred);
                        this.InnerElaborators.Add(innerElaborator);
                        innerElaborator.Elaborate();

                        // delete reference
                        reference.DestroyObject();
                    }
                }
            }

            // FIXME: it is possible for a parentWithDupComponentGuid to contain child CAs that need to be deduped also
            string lastPath = null;

            foreach (var ent in parentsWithDupComponentGuids)
            {
                if (lastPath != null)
                {
                    if (ent.Key.StartsWith(lastPath))
                    {
                        continue;
                    }
                }
                lastPath = ent.Key;
                var model = ent.Value;
                allObjects = model.GetDescendantFCOs(filter);

                var parentGuid = model.ParentModel != null ? model.ParentModel.RegistryValue[RegistryNameInstanceGuidChain] : null;
                // parent model should contain the concatenated InstanceGUID
                string guidConcat = (parentGuid ?? "") + new Guid(model.GetGuidDisp()).ToString("D");
                foreach (MgaFCO obj in allObjects)
                {
                    if (obj.MetaBase.MetaRef == this.Factory.ComponentMeta)
                    {
                        obj.SetStrAttrByNameDisp("InstanceGUID", guidConcat + obj.GetStrAttrByNameDisp("InstanceGUID"));
                    }
                    if (obj.MetaBase.MetaRef == this.Factory.ComponentAssemblyMeta)
                    {
                        obj.RegistryValue[RegistryNameInstanceGuidChain] = guidConcat;
                    }
                }
            }

            this.IsElaborated = true;
        }