void TestAssemblySyncDiscardComponent() { SetupTest(); RunCyPhyMLSync( (project, propagate, interpreter) => { MgaFCO testAssembly; MgaFCO testAssemblyHierarchy_2; MgaFCO componentInstance; string componentInstanceGuid; string testHierarchy_1RefId; string testAssemblyRefId; project.BeginTransactionInNewTerr(); try { var filter = project.CreateFilter(); filter.Kind = "ComponentAssembly"; testAssembly = project.AllFCOs(filter).Cast <MgaFCO>() .Where(fco => fco.GetGuidDisp() == new Guid(testAssemblyId).ToString("B")).First(); testAssemblyHierarchy_2 = project.AllFCOs(filter).Cast <MgaFCO>() .Where(fco => fco.GetGuidDisp() == new Guid(testAssemblyHierarchy_2Id).ToString("B")).First(); //hullAndHookHookGuid = (string)((MgaModel)project.RootFolder.ObjectByPath[hullAndHookHookPath]).GetAttributeByNameDisp("AVMID"); componentInstance = testAssembly.ChildObjects.Cast <MgaFCO>().Where(f => f.Name.Contains("Damper")).First(); componentInstanceGuid = componentInstance.GetStrAttrByNameDisp("InstanceGUID"); MgaReference testHierarchy_1Ref = testAssemblyHierarchy_2.ChildObjects.Cast <MgaFCO>().OfType <MgaReference>().First(); testHierarchy_1RefId = new Guid(testHierarchy_1Ref.GetGuidDisp()).ToString("B"); MgaReference testAssemblyRef = ((MgaModel)testHierarchy_1Ref.Referred).ChildObjects.Cast <MgaFCO>().OfType <MgaReference>().First(); testAssemblyRefId = new Guid(testAssemblyRef.GetGuidDisp()).ToString("B"); } finally { project.AbortTransaction(); } interpreter.StartAssemblySync(project, testAssemblyHierarchy_2, 128); Application.DoEvents(); // wait for metalink bridge to record addon's interest in assembly while (true) { string line; if (metalinkOutput.TryTake(out line, 5000) == false) { throw new TimeoutException("Timed out waiting for metalink bridge to log 'interest recorded'"); } if (line.Contains("interest recorded")) { break; } } var msg = new Edit(); msg.mode.Add(Edit.EditMode.POST); msg.origin.Add(origin); msg.topic.Add((CyPhyMetaLinkAddon.IdCounter - 1).ToString()); var action = new edu.vanderbilt.isis.meta.Action(); action.actionMode = edu.vanderbilt.isis.meta.Action.ActionMode.REMOVE_CYPHY_DESIGN_COMPONENT; action.subjectID = testAssemblyHierarchy_2Id; action.payload = new Payload(); action.payload.components.Add(new CADComponentType() { //ComponentID = hookInstanceGuid, ComponentID = testHierarchy_1RefId + testAssemblyRefId + componentInstanceGuid }); msg.actions.Add(action); SendToMetaLinkBridgeAndWaitForAddonToReceive(msg); WaitForAllMetaLinkMessages(); Application.DoEvents(); project.BeginTransactionInNewTerr(); try { Xunit.Assert.Equal((int)objectstatus_enum.OBJECT_DELETED, componentInstance.Status); } finally { project.AbortTransaction(); } } ); }
/// <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); }