示例#1
0
        /// <summary>
        /// Generic port "clone" function that creates and copies a port/pin or pin.
        /// </summary>
        /// <param name="parent">The MgaModel that will contain newly-created clone</param>
        /// <param name="oldPort">The original port or pin to be cloned</param>
        /// <returns>newPortFCO -- The cloned port/pin created in the parent.</returns>
        private MgaFCO ClonePort(MgaModel parent, MgaFCO oldPort)
        {
            Logger.WriteDebug("ClonePort: {0}", oldPort.AbsPath);

            GME.MGA.Meta.MgaMetaRole role = null;

            foreach (GME.MGA.Meta.MgaMetaRole roleItem in (parent.Meta as GME.MGA.Meta.MgaMetaModel).Roles)
            {
                if (roleItem.Kind.MetaRef == oldPort.MetaBase.MetaRef)
                {
                    role = roleItem;
                    break;
                }
            }

            var newPortFCO = parent.CopyFCODisp(oldPort, role);

            //newPortFCO.SetAttributeByNameDisp("ID", null);
            return(newPortFCO);
        }
示例#2
0
        /// <summary>
        /// Utility function to switch a reference to a model copy or instance. Reference should be deleted after this call.
        /// </summary>
        /// <remarks>In case copy is requested and the target element is a derived type (i.e. subtype or instance) inheritance chain will be cut. To make further elaboration possible.</remarks>
        /// <param name="parentModel">Parent model of the reference</param>
        /// <param name="reference">Reference to switch to a model</param>
        /// <param name="createInstance">If true creates an instance otherwise makes a copy of the target object. See remarks.</param>
        /// <returns>Model which was created instead of the reference.</returns>
        protected MgaModel SwitchReferenceToModel(MgaModel parentModel, MgaReference reference, bool createInstance)
        {
            this.LogDebug("Switching reference to model", reference);

            if (reference.Referred == null)
            {
                // failed to elaborate
                this.Logger.WriteFailed("Reference is null. {0} {1} [{2}]", reference.ID, reference.Name, reference.MetaBase.Name);
                return(null);
            }

            var referred = reference.Referred;

            // FIXME: this could fail, e.g. if componentref refers to a test component and we are in a CA
            GME.MGA.Meta.MgaMetaRole role = null;

            foreach (GME.MGA.Meta.MgaMetaRole roleItem in (parentModel.Meta as GME.MGA.Meta.MgaMetaModel)
                     .Roles)
            {
                if (roleItem.Kind.MetaRef == referred.MetaBase.MetaRef)
                {
                    role = roleItem;
                    break;
                }
            }

            if (role == null)
            {
                throw new ElaboratorException(string.Format("Role was not found for {0} [{1}] in {2} [{3}]", referred.Name, referred.MetaBase.Name, parentModel.Name, parentModel.MetaBase.Name));
            }

            MgaFCO copiedObj = null;

            Func <MgaFCO, MgaFCO, MgaFCO> getOriginalChildObject = null;

            if (createInstance)
            {
                this.LogDebug("Creating instance from", referred);

                MgaFCO originalReferred = null;
                if (UnrollConnectors)
                {
                    originalReferred = referred;
                    MgaFCO referredCopy;
                    if (ComponentCopyMap.TryGetValue(referred, out referredCopy))
                    {
                    }
                    else
                    {
                        // FIXME update traceability
                        referredCopy = referred.ParentFolder.CopyFCODisp(referred);
                        ComponentCopyMap[referred] = referredCopy;
                    }
                    referred = referredCopy;
                }

                copiedObj = parentModel.DeriveChildObject(referred, role, true);

                Func <IMgaFCO, int> getRelID = (fco) => {
                    if (fco.DerivedFrom != null && fco.IsPrimaryDerived == false)
                    {
                        // workaround GME bug fixed 2/27/2017
                        const int RELID_BASE_MAX = 0x07FFFFFF; // Mga.idl
                        return((~RELID_BASE_MAX & fco.RelID) | (RELID_BASE_MAX & fco.DerivedFrom.RelID));
                    }
                    return(fco.RelID);
                };
                Func <MgaFCO, string> getFCORelIds = fco =>
                {
                    string   ret    = "/#" + getRelID(fco);
                    MgaModel parent = fco.ParentModel;
                    while (parent != null)
                    {
                        ret    = "/#" + getRelID(parent) + ret;
                        parent = parent.ParentModel;
                    }
                    return(ret);
                };

                getOriginalChildObject = new Func <MgaFCO, MgaFCO, MgaFCO>((parent, copied) =>
                {
                    if (UnrollConnectors == false)
                    {
                        return(copied.DerivedFrom);
                    }
                    string relPath = getFCORelIds(copied.DerivedFrom).Substring(getFCORelIds(referred).Length);
                    var ret        = (MgaFCO)originalReferred.GetObjectByPathDisp(relPath);
                    if (ret == null)
                    {
                        ret = originalReferred;
                        // GME bug workaround continued
                        foreach (var relID in relPath.Substring(2).Split(new[] { "/#" }, StringSplitOptions.None))
                        {
                            ret = ret.ChildObjects.Cast <MgaFCO>().Where(f => getRelID(f).ToString() == relID).First();
                        }
                        if (ret == null)
                        {
                            throw new ArgumentNullException();
                        }
                    }
                    return(ret);
                });

                var guid = reference.StrAttrByName[AttributeNameInstanceGuid];
                if (string.IsNullOrWhiteSpace(guid))
                {
                    reference.set_StrAttrByName(AttributeNameInstanceGuid, reference.GetGuidDisp());
                    guid = reference.StrAttrByName[AttributeNameInstanceGuid];
                    this.LogDebug("InstanceGUID was empty for reference, assigned new : " + guid, reference);
                }

                // parent model should contain the concatenated InstanceGUID
                string guidConcat = parentModel.RegistryValue[RegistryNameInstanceGuidChain] + guid;

                copiedObj.RegistryValue[RegistryNameInstanceGuidChain]  = guidConcat;
                copiedObj.RegistryValue[RegistryNameOriginalReferredID] = reference.Referred.ID;

                this.LogDebug(string.Format("Overwriting InstanceGUID to {0}", guidConcat), referred);

                copiedObj.StrAttrByName[AttributeNameInstanceGuid] = guidConcat;

                copiedObj.RegistryValue[RegistryNameGmeIDChain] = parentModel.RegistryValue[RegistryNameGmeIDChain] + "," + reference.ID + "," + referred.ID;
            }
            else
            {
                this.LogDebug("Creating copy from", referred);

                copiedObj = parentModel.CopyFCODisp(referred, role);

                if (copiedObj.ArcheType != null)
                {
                    // instance or subtype
                    this.LogDebug("Cutting inheritance for copied object", copiedObj);
                    copiedObj.DetachFromArcheType();
                }

                getOriginalChildObject = new Func <MgaFCO, MgaFCO, MgaFCO>((parent, copied) =>
                {
                    // only chance to find objects are based on relids, which might not be unique
                    return(parent.ChildObjectByRelID[copied.RelID] as MgaFCO);
                });

                copiedObj.RegistryValue[RegistryNameGmeIDChain] = parentModel.RegistryValue[RegistryNameGmeIDChain] + "," + reference.ID + "," + referred.ID;

                if (reference.MetaBase.MetaRef == this.Factory.ComponentRefMeta)
                {
                    var guid = reference.StrAttrByName[AttributeNameInstanceGuid];

                    copiedObj.RegistryValue[RegistryNameInstanceGuidChain]  = parentModel.RegistryValue[RegistryNameInstanceGuidChain] + guid;
                    copiedObj.RegistryValue[RegistryNameOriginalReferredID] = reference.Referred.ID;

                    // push current instance GUID down to all component assembly elements
                    MgaFilter filter = copiedObj.Project.CreateFilter();
                    filter.ObjType = GME.MGA.Meta.objtype_enum.OBJTYPE_MODEL.ToString();
                    // filter.Kind = "ComponentAssembly";

                    foreach (MgaFCO obj in (copiedObj as MgaModel).GetDescendantFCOs(filter))
                    {
                        if (obj.MetaBase.MetaRef == this.Factory.ComponentAssemblyMeta)
                        {
                            obj.RegistryValue[RegistryNameInstanceGuidChain] = copiedObj.RegistryValue[RegistryNameInstanceGuidChain];

                            obj.RegistryValue[RegistryNameGmeIDChain] = copiedObj.RegistryValue[RegistryNameGmeIDChain];
                        }
                    }
                }
            }

            copiedObj.Name = reference.Name;
            if (reference.Meta.MetaRef == this.Factory.ComponentRefMeta && copiedObj.Meta.MetaRef == this.Factory.ComponentAssemblyMeta)
            {
                // TODO what should happen here
                // var managedGuid = reference.StrAttrByName["ManagedGUID"]; ComponentRef does not have ManagedGUID
                var managedGuid = reference.StrAttrByName["InstanceGUID"];
                if (string.IsNullOrEmpty(managedGuid) == false)
                {
                    //    copiedObj.StrAttrByName["ManagedGUID"] = managedGuid;
                }
            }

            foreach (MgaPart part in reference.Parts)
            {
                int    x;
                int    y;
                string icon;
                part.GetGmeAttrs(out icon, out x, out y);

                try
                {
                    copiedObj.Part[part.MetaAspect].SetGmeAttrs(icon, x, y);
                }
                catch (System.Runtime.InteropServices.COMException)
                {
                    // It's okay. This means that Reference is visible in this aspect, but copiedObj isn't
                }
            }

            // add / update to traceability
            string baseId = null;

            if (this.Traceability.TryGetValue(reference.ID, out baseId))
            {
                //// if it is already in the traceability it is a temporary object.
                //// we need our final object in the mapping

                this.Traceability.Remove(reference.ID);
                this.Traceability.Add(copiedObj.ID, baseId);
            }
            else
            {
                this.Traceability.Add(copiedObj.ID, referred.ID);
            }

            // safe connection information for switching connections later.
            Dictionary <MgaFCO, MgaFCO> original2Copied = new Dictionary <MgaFCO, MgaFCO>();

            original2Copied.Add(referred, copiedObj);

            MgaFCOs objects = null;

            if (createInstance)
            {
                objects = (copiedObj as MgaModel).GetDescendantFCOs(copiedObj.Project.CreateFilter());
            }
            else
            {
                objects = (copiedObj as MgaModel).ChildFCOs;
            }

            foreach (MgaFCO copied in objects)
            {
                if (copied == copiedObj)
                {
                    continue;
                }

                var original = getOriginalChildObject(referred, copied);
                original2Copied.Add(original, copied);

                if (this.Traceability.TryGetValue(original.ID, out baseId))
                {
                    // if it is already in the traceability it is a temporary object.
                    // we need our final object in the mapping
                    this.Traceability.Remove(original.ID);
                    this.Traceability.Add(copied.ID, baseId);
                }
                else
                {
                    this.Traceability.Add(copied.ID, original.ID);
                }

                if (!createInstance && copied.ObjType == GME.MGA.Meta.objtype_enum.OBJTYPE_MODEL)
                {
                    this.AddRecursivelyTraceability(copied, original);
                }
            }

            // switch connections to refport children
            foreach (MgaConnPoint connPoint in reference.UsedByConns)
            {
                var connection = connPoint.Owner as IMgaSimpleConnection;

                if (connPoint.ConnRole == "src" &&
                    connection.SrcReferences.Count > 0 &&
                    connection.SrcReferences[1] == reference)
                {
                    // what if this is instance
                    var newEndPoint = original2Copied[connection.Src];

                    if (newEndPoint == null)
                    {
                        throw new Exception("null connection endpoint");
                    }

                    // create an empty array for the connection references
                    MgaFCOs emptyArray = (MgaFCOs)Activator.CreateInstance(Elaborator.MgaFCOsType);
                    connection.SetSrc(emptyArray, newEndPoint);
                }

                if (connPoint.ConnRole == "dst" &&
                    connection.DstReferences.Count > 0 &&
                    connection.DstReferences[1] == reference)
                {
                    // what if this is instance
                    var newEndPoint = original2Copied[connection.Dst];

                    if (newEndPoint == null)
                    {
                        throw new Exception("null connection endpoint");
                    }

                    // create an empty array for the connection references
                    MgaFCOs emptyArray = (MgaFCOs)Activator.CreateInstance(Elaborator.MgaFCOsType);
                    connection.SetDst(emptyArray, newEndPoint);
                }
            }

            // switch connections to original reference object itself
            foreach (MgaConnPoint connPoint in reference.PartOfConns)
            {
                var connection = connPoint.Owner as IMgaSimpleConnection;

                if (connPoint.ConnRole == "src")
                {
                    // create an empty array for the connection references
                    MgaFCOs emptyArray = (MgaFCOs)Activator.CreateInstance(Elaborator.MgaFCOsType);
                    try
                    {
                        connection.SetSrc(emptyArray, copiedObj);
                    }
                    catch (COMException ex)
                    {
                        if (ex.Message.Contains("Illegal connection") &&
                            ex.Message.Contains("meta violation"))
                        {
                            var refID = reference.ID;
                            while (Traceability.ContainsKey(refID))
                            {
                                refID = Traceability[refID];
                            }

                            Logger.WriteWarning("<a href=\"mga:{0}\">{1}</a>'s referred type ({2}) isn't a legal SRC target for {3} connections. Skipping re-creation of this connection.",
                                                refID,
                                                reference.Name,
                                                reference.Referred.MetaBase.Name,
                                                connection.MetaBase.Name);
                        }
                        else
                        {
                            throw ex;
                        }
                    }
                }
                else if (connPoint.ConnRole == "dst")
                {
                    // create an empty array for the connection references
                    MgaFCOs emptyArray = (MgaFCOs)Activator.CreateInstance(Elaborator.MgaFCOsType);
                    try
                    {
                        connection.SetDst(emptyArray, copiedObj);
                    }
                    catch (COMException ex)
                    {
                        if (ex.Message.Contains("Illegal connection") &&
                            ex.Message.Contains("meta violation"))
                        {
                            var refID = reference.ID;
                            while (Traceability.ContainsKey(refID))
                            {
                                refID = Traceability[refID];
                            }

                            Logger.WriteWarning("<a href=\"mga:{0}\">{1}</a>'s referred type ({2}) isn't a legal DST target for {3} connections. Skipping re-creation of this connection.",
                                                refID,
                                                reference.Name,
                                                reference.Referred.MetaBase.Name,
                                                connection.MetaBase.Name);
                        }
                        else
                        {
                            throw ex;
                        }
                    }
                }
            }

            return(copiedObj as MgaModel);
        }