public IMgaFCOs ImportFiles(MgaProject project, string projRootPath, string[] FileNames, bool alwaysReplace = false, bool doNotReplaceAll = false) { Boolean b_CLMAddOnStatus = META.ComponentLibraryManagerAddOn.GetEnabled(project); META.ComponentLibraryManagerAddOn.Enable(false, project); var addons = project.AddOnComponents.Cast <IMgaComponentEx>(); foreach (var addon in addons) { if (addon.ComponentName.ToLowerInvariant() == "CyPhyAddOn".ToLowerInvariant()) { addon.ComponentParameter["DontAssignGuidsOnNextTransaction".ToLowerInvariant()] = true; } } IMgaFCOs importedComponents = (IMgaFCOs)Activator.CreateInstance(Type.GetTypeFromProgID("Mga.MgaFCOs")); try { bool replaceAll = alwaysReplace; CyPhy.RootFolder rootFolder = ISIS.GME.Common.Utils.CreateObject <CyPhyClasses.RootFolder>(project.RootFolder as MgaObject); Dictionary <string, CyPhy.Component> avmidComponentMap = getCyPhyMLComponentDictionary_ByAVMID(rootFolder); Dictionary <string, CyPhy.Component> nameComponentMap = getCyPhyMLComponentDictionary_ByName(rootFolder); Boolean b_FirstComponent = true; foreach (String inputFile in FileNames) { var inputFilePath = inputFile; /* Disable validation for now #region Check validation rules * * var errorMessages = new List<string>(); * ComponentImportRules.CheckUniqueNames(inputXMLFile, ref errorMessages); * var isValid = ComponentImportRules.ValidateXsd(inputXMLFile, ref errorMessages); * * foreach (var errorMessage in errorMessages) * { * GMEConsole.Error.WriteLine(errorMessage); * } * * if (!isValid) * { * GMEConsole.Info.WriteLine("XML is not valid. Skip file: {0}", inputXMLFile); * continue; * } #endregion */ GMEConsole.Info.WriteLine("Importing {0}", inputFilePath); // If ZIP file, unzip it to a temporary directory, then import as usual UnzipToTemp unzip = null; bool bZipArchive = (Path.GetExtension(inputFilePath) == ".zip"); if (bZipArchive) { unzip = new UnzipToTemp(GMEConsole); List <string> entries = unzip.UnzipFile(inputFilePath); inputFilePath = entries.Where(entry => Path.GetDirectoryName(entry) == "" && entry.EndsWith(".acm")).FirstOrDefault(); if (inputFilePath != null) { inputFilePath = Path.Combine(unzip.TempDirDestination, inputFilePath); } } using (unzip) try { if (inputFilePath == null) // may be null if .zip didn't contain .acm { throw new FileNotFoundException("No ACM file not found in root directory of ZIP file."); } avm.Component ac_import = null; /* META-3003: Check for old-style ITAR statement */ bool isDistributionD = false; bool isNotItar = false; #region Check for old-style ITAR statements XmlDocument doc = new XmlDocument(); doc.Load(inputFilePath); XmlNode root = doc.DocumentElement; XmlNodeList nodeList = root.SelectNodes("//*[local-name()='DistributionRestriction' and @Level='ITARDistributionD']"); if (nodeList.Count > 0) { isDistributionD = true; } else { nodeList = root.SelectNodes("//*[local-name()='DistributionRestriction' and @Level='NotITAR']"); if (nodeList.Count > 0) { isNotItar = true; } } #endregion using (StreamReader streamReader = new StreamReader(inputFilePath)) { ac_import = DeserializeAvmComponentXml(streamReader); } if (ac_import == null) { throw new Exception("Could not load ACM file."); } /* Throw warning if from an unexpected schema version */ CheckAndWarnOnSchemaVersion(ac_import); /* META-3003: Strip old-style ITAR statement */ #region Strip old-style ITAR statements if (isDistributionD) { // Correct this. if (ac_import.DistributionRestriction == null) { ac_import.DistributionRestriction = new List <avm.DistributionRestriction>(); } ac_import.DistributionRestriction.Add(new avm.DoDDistributionStatement() { Type = DoDDistributionStatementEnum.StatementD }); } else if (isNotItar) { var itar = ac_import.DistributionRestriction.OfType <avm.ITAR>().FirstOrDefault(); if (itar != null) { ac_import.DistributionRestriction.Remove(itar); } } #endregion String acmDir = Path.GetDirectoryName(inputFilePath); #region File Management // Create a new backend folder String compDirAbsPath = META.ComponentLibraryManager.CreateComponentFolder(project); String compDirRelPath = MetaAvmProject.MakeRelativePath(projRootPath, compDirAbsPath); // Copy the ACM file to the new path String newACMRelPath = Path.Combine(compDirRelPath, ac_import.Name + ".acm"); string newACMAbsPath = Path.Combine(compDirAbsPath, ac_import.Name + ".acm"); File.Copy(inputFilePath, newACMAbsPath, true); // Now we have to copy in his resources foreach (var resource in ac_import.ResourceDependency) { try { var dirRelPath = Path.GetDirectoryName(resource.Path); var dirAbsPath = Path.Combine(compDirAbsPath, dirRelPath); var orgAbsPath = Path.Combine(acmDir, resource.Path); var dstAbsPath = Path.Combine(compDirAbsPath, resource.Path); Directory.CreateDirectory(dirAbsPath); File.Copy(orgAbsPath, dstAbsPath, true); } catch (FileNotFoundException) { var message = String.Format("This Component depends on a file which cannot be found in the Component package: {0}", resource.Path); GMEConsole.Warning.WriteLine(message); } catch (DirectoryNotFoundException) { var message = String.Format("This Component depends on a file which cannot be found in the Component package: {0}", resource.Path); GMEConsole.Warning.WriteLine(message); } catch (PathTooLongException) { var message = String.Format("This Component has a Resource that results in a path that is too long: {0}", resource.Path); GMEConsole.Warning.WriteLine(message); } catch (NotSupportedException) { var message = String.Format("This Component has a Resource that could not be loaded: {0}", resource.Path); GMEConsole.Warning.WriteLine(message); } catch (Exception ex) { var message = String.Format("Exception while copying Resource {0}: {1}", resource.Path, ex); GMEConsole.Warning.WriteLine(message); } } #endregion CyPhy.ComponentAssembly cyPhyMLComponentAssembly = null; CyPhy.Components cyPhyMLComponentsFolder = null; CyPhy.Component cyPhyReplaceComponent = null; #region Search for Components that should be Replaced by this new one bool replaceeFound = false; if (ac_import.ID != null) { replaceeFound = avmidComponentMap.TryGetValue(ac_import.ID, out cyPhyReplaceComponent); } if (replaceeFound == false) { replaceeFound = nameComponentMap.TryGetValue(ac_import.Name, out cyPhyReplaceComponent); } if (replaceeFound) { bool replace = false; if (!doNotReplaceAll && !replaceAll) { // Present dialog to see if user wants to replace component with AVMID avmid // Maybe have a "do all" checkbox (which sets "replaceAll" to "true") if many items are being imported. // If yes, replace = true; String s_ExistingName = cyPhyReplaceComponent.Name; String s_ExistingAVMID = cyPhyReplaceComponent.Attributes.AVMID; String s_ExistingVersion = cyPhyReplaceComponent.Attributes.Version; String s_ExistingRevision = cyPhyReplaceComponent.Attributes.Revision; String s_ExistingDescriptor = cyPhyReplaceComponent.Name; if (s_ExistingAVMID != "") { s_ExistingDescriptor += "\nAVM ID: " + s_ExistingAVMID; } if (s_ExistingVersion != "") { s_ExistingDescriptor += "\nVersion: " + s_ExistingVersion; } if (s_ExistingRevision != "") { s_ExistingDescriptor += "\nRevision: " + s_ExistingRevision; } String s_NewName = ac_import.Name; //String s_NewAVMID = ac_import.AVMID; String s_NewVersion = ac_import.Version; //String s_NewRevision = ac_import.Revision; String s_NewDescriptor = ac_import.Name; //if (s_NewAVMID != "") // s_NewDescriptor += "\nAVM ID: " + s_NewAVMID; if (s_NewVersion != "") { s_NewDescriptor += "\nVersion: " + s_NewVersion; } //if (s_NewRevision != "") // s_NewDescriptor += "\nRevision: " + s_NewRevision; String s_MessageBoxPromptTemplate = "Would you like to replace\n\n{0}\n\nwith\n\n{1}"; String s_MessageBoxPrompt = String.Format(s_MessageBoxPromptTemplate, s_ExistingDescriptor, s_NewDescriptor); using (UpdatePrompt up = new UpdatePrompt()) { up.DialogText.Text = s_MessageBoxPrompt; up.ShowDialog(); if (up.DialogResult == DialogResult.Cancel || up.DialogResult == DialogResult.None) { // Skip this component; Continues the "foreach" loop above. GMEConsole.Error.WriteLine("Import canceled for {0}", inputFile); continue; } Dictionary <DialogResult, string> d_TranslateResult = new Dictionary <DialogResult, string>() { { DialogResult.OK, "Replace" }, { DialogResult.Abort, "Import as New" }, }; if (d_TranslateResult[up.DialogResult] == "Replace") { replace = true; if (up.applyToAll.Checked) { replaceAll = true; } } else if (d_TranslateResult[up.DialogResult] == "Import as New") { if (up.applyToAll.Checked) { doNotReplaceAll = true; } } } } if (!replace && !replaceAll || doNotReplaceAll) { cyPhyReplaceComponent = null; } } #endregion if (cyPhyReplaceComponent != null) { Object replaceComponentParent = cyPhyReplaceComponent.ParentContainer; if (replaceComponentParent is CyPhy.ComponentAssembly) { cyPhyMLComponentAssembly = replaceComponentParent as CyPhy.ComponentAssembly; } else { cyPhyMLComponentsFolder = replaceComponentParent as CyPhy.Components; } } else { cyPhyMLComponentsFolder = GetImportFolder(rootFolder); } // The importer uses a map to resolve unit references. // If this is our second run, we shouldn't waste time rebuilding it. Boolean b_ResetUnitMap; if (b_FirstComponent) { b_ResetUnitMap = true; } else { b_ResetUnitMap = false; } CyPhy.Component c = null; if (cyPhyMLComponentAssembly != null) { c = CyPhy2ComponentModel.Convert.AVMComponent2CyPhyML(cyPhyMLComponentAssembly, ac_import, b_ResetUnitMap, GMEConsole); } else { c = CyPhy2ComponentModel.Convert.AVMComponent2CyPhyML(cyPhyMLComponentsFolder, ac_import, b_ResetUnitMap, GMEConsole); } if (c != null) { importedComponents.Append(c.Impl as MgaFCO); c.Attributes.Path = compDirRelPath; } if (cyPhyReplaceComponent != null) { foreach (IMgaReference reference in (cyPhyReplaceComponent.Impl as IMgaFCO).ReferencedBy) { ReferenceSwitcher.Switcher.MoveReferenceWithRefportConnections(c.Impl as IMgaFCO, reference, WriteLine); } cyPhyReplaceComponent.Delete(); } // If icon available, set it in Preferences. // Relative paths here are from our project root. var iconResource = ac_import.ResourceDependency.Where(x => x.Path.Contains("Icon.png")).FirstOrDefault(); //foreach (AVM.File file in ac_import.Files) //{ // if (file.Location.Contains("Icon.png")) // iconRelativePath = componentModelRelativePath + "/" + file.Location; //} if (iconResource != null) { var iconRelativePath = Path.Combine(compDirRelPath, iconResource.Path); // Remove leading "\" if (iconRelativePath.IndexOf("\\") == 0) { iconRelativePath = iconRelativePath.Remove(0, 1); } // Shrink double backslash to single iconRelativePath = iconRelativePath.Replace("\\\\", "\\"); // Replace / with \ iconRelativePath = iconRelativePath.Replace('/', '\\'); // If icon exists, set it if (System.IO.File.Exists(iconRelativePath)) { // Set "icon" regnode (c.Impl as GME.MGA.IMgaFCO).set_RegistryValue("icon", iconRelativePath); } } GMEConsole.Info.WriteLine("Imported {0} to <a href=\"mga:{2}\">{1}</a>", inputFile, SecurityElement.Escape(c.Name), c.ID); } catch (Exception ex) { string error = string.Format("{0} while importing {1}: {2}", ex.GetType().Name, inputFile, ex.Message); GMEConsole.Error.WriteLine(error); this.Errors.Add(error); GMEConsole.Error.WriteLine(ex.StackTrace); } finally { } b_FirstComponent = false; } } finally { // Reset the "enabled" state of the CLM AddOn META.ComponentLibraryManagerAddOn.Enable(b_CLMAddOnStatus, project); } return(importedComponents); }
/// <summary> /// Given a component, ensures that the component has a backend folder /// for storing resources. Ensures that the Component has an AVMID unique /// to the project. Creates a folder if necessary. /// </summary> /// <param name="component"></param> /// <param name="ProjectDirectory">Directory in which the /components/ folder resides. Defaults to project directory of <paramref name="component"/></param> /// <returns>The path of the Component folder, relative to the project root</returns> public static String EnsureComponentFolder(CyPhy.Component component, string ProjectDirectory = null) { Boolean bIsArchetype = (component.ParentContainer.Kind == "Components"); String path = ""; EnsureAVMID(component); var mp_MgaProject = component.Impl.Project; String p_ProjectRoot = ProjectDirectory ?? mp_MgaProject.GetRootDirectoryPath(); // META-2640 use full path instead of relative project path if (p_ProjectRoot == "") { p_ProjectRoot = "."; } p_ProjectRoot = Path.GetFullPath(p_ProjectRoot); var lastChar = p_ProjectRoot.Last(); if (lastChar != '\\' && lastChar != '/') { p_ProjectRoot += '\\'; } // Try to get a path from the CyPhy model. // If that fails, check the manifest. Boolean bHasFolderSpecified = false; if (!String.IsNullOrWhiteSpace(component.Attributes.Path)) { bHasFolderSpecified = true; path = component.Attributes.Path; // Strip filename if necessary if (path.EndsWith(".acm")) { path = Path.GetDirectoryName(path); } else if (path.EndsWith("ComponentData.xml")) { path = Path.GetDirectoryName(path); } } else { // If a project file already exists, this will load it. MetaAvmProject proj = MetaAvmProject.Create(p_ProjectRoot, component.Impl.Project, null, GMEConsole.CreateFromProject(mp_MgaProject)); // Check to see if this component has a folder already. var c_CompEntryInProjectFile = proj.Project.Components.Find(x => x.avmid == component.Attributes.AVMID); if (c_CompEntryInProjectFile != null) { bHasFolderSpecified = true; path = Path.GetDirectoryName(c_CompEntryInProjectFile.modelpath); } } bHasFolderSpecified = bHasFolderSpecified && !PathContainsIllegalChar(path); if (bHasFolderSpecified && !Directory.Exists(path)) { Directory.CreateDirectory(path); } // Only create new folders for archetypes else if (!bHasFolderSpecified && bIsArchetype) { var absPath = CreateComponentFolder(mp_MgaProject); path = MakeRelativePath(p_ProjectRoot, absPath); path = path.Replace('\\', '/') + '/'; } // Strip any leading path character if (path.Length >= 2 && (path.Substring(0, 2) == "./" || path.Substring(0, 2) == ".\\")) { path = path.Remove(0, 2); } // Store the path in the component's attribute for faster retrieval next time. component.Attributes.Path = path; return(path); }