Exemplo n.º 1
0
        /// <summary>
        /// Called when an FCO or folder changes
        /// </summary>
        /// <param name="subject">the object the event(s) happened to</param>
        /// <param name="eventMask">objectevent_enum values ORed together</param>
        /// <param name="param">extra information provided for cetertain event types</param>
        public void ObjectEvent(MgaObject subject, uint eventMask, object param)
        {
            if (!componentEnabled)
            {
                return;
            }
            if (!handleEvents)
            {
                return;
            }
            uint uOBJEVENT_CREATED = 0;

            unchecked { uOBJEVENT_CREATED = (uint)objectevent_enum.OBJEVENT_CREATED; }
            bool objectCreatedAndNotLibObject = (eventMask & uOBJEVENT_CREATED) != 0 && (eventMask & (uint)objectevent_enum.OBJEVENT_DESTROYED) == 0 && subject.IsLibObject == false;

            if (xmeImportInProgress)
            {
                if (objectCreatedAndNotLibObject && subject.MetaBase.MetaRef == componentAssemblyMetaRef && componentAssemblyPathMetaRef != 0)
                {
                    string path = ((IMgaFCO)subject).StrAttrByName["Path"];
                    if (path == "")
                    {
                        ((IMgaFCO)subject).StrAttrByName["Path"] = GetRandomComponentAssemblyDir();
                    }
                }
                return;
            }

            // TODO: Handle object events (OR eventMask with the members of objectevent_enum)
            // Warning: Only those events are received that you have subscribed for by setting ComponentConfig.eventMask

            // If the event is OBJEVENT_DESTROYED, most operations on subject will fail
            //   Safe operations: getting Project, ObjType, ID, MetaRole, Meta, MetaBase, Name, AbsPath
            //   Operations that will fail: all others, including attribute access and graph navigation
            //     Try handling OBJEVENT_PRE_DESTROYED if these operations are necessary

            // Be careful not to modify Library objects (check subject.IsLibObject)

            // MessageBox.Show(eventMask.ToString());
            // GMEConsole.Out.WriteLine(subject.Name);

            // attribute was changed and object was neither created nor destroyed
            bool attributeChanged = (eventMask & (uint)objectevent_enum.OBJEVENT_ATTR) != 0 &&
                                    (eventMask & uOBJEVENT_CREATED) == 0 &&
                                    (eventMask & (uint)objectevent_enum.OBJEVENT_DESTROYED) == 0;

            if (objectCreatedAndNotLibObject)
            {
                MgaObject parent;
                GME.MGA.Meta.objtype_enum objType;
                subject.GetParent(out parent, out objType);
                // Object was created
                if (subject.MetaBase.Name == "Component")
                {
                    // Check that parent is a Components folder
                    if (objType == GME.MGA.Meta.objtype_enum.OBJTYPE_FOLDER &&
                        parent.MetaBase.Name == "Components")
                    {
                        Process(CyPhyClasses.Component.Cast(subject));
                    }
                }
                else if (subject.MetaBase.Name == "ComponentAssembly")
                {
                    Process(CyPhyClasses.ComponentAssembly.Cast(subject));
                }
            }
            else if (attributeChanged && subject.IsLibObject == false)
            {
                MgaObject parent;
                GME.MGA.Meta.objtype_enum objType;
                subject.GetParent(out parent, out objType);
                if (subject.MetaBase.Name == "Component")
                {
                    string oldPath = null;
                    // Check that parent is a Components folder
                    if (objType == GME.MGA.Meta.objtype_enum.OBJTYPE_FOLDER &&
                        parent.MetaBase.Name == "Components")
                    {
                        if (param != null)
                        {
                            var parameters = ((object[])param).ToList();
                            int pathAttr   = parameters.IndexOf("ATTR:Path");
                            if (pathAttr != -1)
                            {
                                oldPath = (string)parameters[pathAttr + 1];
                                RenameComponentDirectory(CyPhyClasses.Component.Cast(subject), oldPath);
                            }
                        }
                    }
                }
            }
        }
Exemplo n.º 2
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>
        /// Called when an FCO or folder changes
        /// </summary>
        /// <param name="subject">the object the event(s) happened to</param>
        /// <param name="eventMask">objectevent_enum values ORed together</param>
        /// <param name="param">extra information provided for cetertain event types</param>
        public void ObjectEvent(MgaObject subject, uint eventMask, object param)
        {
            if (!componentEnabled)
            {
                return;
            }
            if (!handleEvents)
            {
                return;
            }
            uint uOBJEVENT_CREATED = 0;
            unchecked { uOBJEVENT_CREATED = (uint)objectevent_enum.OBJEVENT_CREATED; }
            bool objectCreatedAndNotLibObject = (eventMask & uOBJEVENT_CREATED) != 0 && (eventMask & (uint)objectevent_enum.OBJEVENT_DESTROYED) == 0 && subject.IsLibObject == false;
            if (xmeImportInProgress)
            {
                if (objectCreatedAndNotLibObject && subject.MetaBase.MetaRef == componentAssemblyMetaRef && componentAssemblyPathMetaRef != 0)
                {
                    string path = ((IMgaFCO)subject).StrAttrByName["Path"];
                    if (path == "")
                    {
                        ((IMgaFCO)subject).StrAttrByName["Path"] = GetRandomComponentAssemblyDir();
                    }
                }
                return;
            }

            // TODO: Handle object events (OR eventMask with the members of objectevent_enum)
            // Warning: Only those events are received that you have subscribed for by setting ComponentConfig.eventMask

            // If the event is OBJEVENT_DESTROYED, most operations on subject will fail
            //   Safe operations: getting Project, ObjType, ID, MetaRole, Meta, MetaBase, Name, AbsPath
            //   Operations that will fail: all others, including attribute access and graph navigation
            //     Try handling OBJEVENT_PRE_DESTROYED if these operations are necessary

            // Be careful not to modify Library objects (check subject.IsLibObject)

            // MessageBox.Show(eventMask.ToString());
            // GMEConsole.Out.WriteLine(subject.Name);

            // attribute was changed and object was neither created nor destroyed
            bool attributeChanged = (eventMask & (uint)objectevent_enum.OBJEVENT_ATTR) != 0 &&
                (eventMask & uOBJEVENT_CREATED) == 0 &&
                (eventMask & (uint)objectevent_enum.OBJEVENT_DESTROYED) == 0;

            if (objectCreatedAndNotLibObject)
            {
                MgaObject parent;
                GME.MGA.Meta.objtype_enum objType;
                subject.GetParent(out parent, out objType);
                // Object was created
                if (subject.MetaBase.Name == "Component")
                {
                    // Check that parent is a Components folder
                    if (objType == GME.MGA.Meta.objtype_enum.OBJTYPE_FOLDER
                        && parent.MetaBase.Name == "Components")
                    {
                        Process(CyPhyClasses.Component.Cast(subject));
                    }
                }
                else if (subject.MetaBase.Name == "ComponentAssembly")
                {
                    Process(CyPhyClasses.ComponentAssembly.Cast(subject));
                }
            }
            else if (attributeChanged && subject.IsLibObject == false)
            {
                MgaObject parent;
                GME.MGA.Meta.objtype_enum objType;
                subject.GetParent(out parent, out objType);
                if (subject.MetaBase.Name == "Component")
                {
                    string oldPath = null;
                    // Check that parent is a Components folder
                    if (objType == GME.MGA.Meta.objtype_enum.OBJTYPE_FOLDER
                        && parent.MetaBase.Name == "Components")
                    {
                        if (param != null)
                        {
                            var parameters = ((object[])param).ToList();
                            int pathAttr = parameters.IndexOf("ATTR:Path");
                            if (pathAttr != -1)
                            {
                                oldPath = (string)parameters[pathAttr + 1];
                                RenameComponentDirectory(CyPhyClasses.Component.Cast(subject), oldPath);
                            }
                        }
                    }
                }

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