/// <summary> /// Raise the TreeNodeChanged event. /// </summary> /// <param name="childrenChanged">Whether the children of this node also changed.</param> /// <param name="node">The node that changed.</param> public override void RaiseNodeChangedEvent(ProjectFileTreeNode node, bool childrenChanged) { if (TreeNodeChanged != null && treeRestructuring == false) { TreeNodeChanged(this, new ProjectFileTreeChangedEventArgs(node, childrenChanged)); } }
/// <summary> /// Raise the TreeNodeChanged event. /// </summary> /// <param name="childrenChanged">Whether the children of this node also changed.</param> /// <param name="node">The node that changed.</param> public virtual void RaiseNodeChangedEvent(ProjectFileTreeNode node, bool childrenChanged) { if (parentTree != null) { parentTree.RaiseNodeChangedEvent(node, childrenChanged); } }
public ProjectFileTreeNode CreateFileNodeForPath(string path) { var pathParts = path.Split(System.IO.Path.DirectorySeparatorChar); ProjectFileTreeNode newNode = this; for (int i = 0; i < pathParts.Length; i++) { var part = pathParts[i]; if (part == ".") { continue; } var possibleChild = newNode.ChildNodes.FirstOrDefault(child => child.Text == part); // Only create a new node if we can't find one already named that. if (possibleChild != null) { newNode = possibleChild; } else { newNode = newNode.AddChildNode(part); } newNode.IsExternalToOutputFolder = System.IO.Path.IsPathRooted(path); if (i < pathParts.Length - 1) { newNode.IsFolder = true; } } // Return the last node created return(newNode); }
public virtual void AddItemToQueue(ProjectFileTreeNode node) { lock (nodesToProcess) { nodesToProcess.Add(node); } }
public virtual void ShiftToFrontOfQueue(ProjectFileTreeNode node) { lock (nodesToProcess) { if (nodesToProcess.Contains(node)) { nodesToProcess.Remove(node); nodesToProcess.Insert(0, node); } } }
public virtual ProjectFileTreeNode Dequeue() { lock (nodesToProcess) { if (nodesToProcess.Count != 0) { ProjectFileTreeNode node = nodesToProcess[0]; nodesToProcess.RemoveAt(0); return(node); } } return(null); }
/// <summary> /// Does a depth first search and returns the first node that satisfies the SearchCondition. /// </summary> /// <param name="node"></param> /// <param name="condition"></param> /// <returns></returns> public static ProjectFileTreeNode DepthFirstSearch(ProjectFileTreeNode node, ProjectFileSearchCondition condition) { if (condition.Satisfied(node)) { return(node); } foreach (ProjectFileTreeNode childNode in node.ChildNodes) { ProjectFileTreeNode result = DepthFirstSearch(childNode, condition); if (result != null) { return(result); } } return(null); }
/// <summary> /// Creates a new node and adds it as a child. /// </summary> /// <param name="associatedFileInformation">The IFileInformation to associated with the node. Can be null if it needs to be set later.</param> /// <param name="nodeText">The text of the node. Can be null if it needs to be set later.</param> /// <returns>The created node.</returns> public virtual ProjectFileTreeNode AddChildNode(IFileInformation associatedFileInformation, String nodeText) { if (nodeText == null) { nodeText = ""; } ProjectFileTreeNode node = new ProjectFileTreeNode(this, parentTree); node.Text = nodeText; node.associatedFile = associatedFileInformation; if (childNodes.Any(c => c.Text == nodeText)) { log.ErrorFormat("Duplicated {0} node called {1}", associatedFileInformation == null ? "folder" : "file", nodeText); } childNodes.Add(node); parentTree.AddNode(node); status = ProjectFileStatusEnum.Folder; RaiseNodeChangedEvent(this, true); return(node); }
private static void LoadMD5sForNode(ProjectFileTreeNode node, string dir) { if (node.IsFolder == false) { return; } string manifestFile = System.IO.Path.Combine(dir, ManifestConstants.MANIFEST_FILENAME); if (File.Exists(manifestFile) == false) { return; } XmlDocument doc = new XmlDocument(); try { doc.Load(manifestFile); } catch (Exception) { return; } foreach (ProjectFileTreeNode childNode in node.ChildNodes) { if (childNode.AssociatedFile != null) { string userMD5, templateMD5, prevgenMD5; PrevGenUtility.GetMD5sForFile(doc, System.IO.Path.GetFileName(childNode.Path), out prevgenMD5, out templateMD5, out userMD5); childNode.AssociatedFile.SetPreviousVersionMD5s(prevgenMD5, templateMD5, userMD5); } else if (childNode.IsFolder) { LoadMD5sForNode(childNode, System.IO.Path.Combine(dir, childNode.Text)); } } }
/// <summary> /// Creates the actual files, or returns a count of the number of files that will be created, depending on value of createFiles. /// </summary> /// <param name="folderName"></param> /// <param name="script"></param> /// <param name="parentNode"></param> /// <returns></returns> private int CreateScriptFile(string folderName, IScript script, ProjectFileTreeNode parentNode) { int fileCount = 0; if (string.IsNullOrEmpty(script.IteratorName)) { if (ProcessScriptObject(null, folderName, script, parentNode)) { fileCount++; } return(fileCount); } ProviderInfo provider; Type iteratorType = _Project.GetIteratorTypeFromProviders(script.IteratorName, out provider); IScriptBaseObject[] iteratorObjects = GetIteratorObjects(iteratorType, provider); if (iteratorObjects != null) { if (iteratorType.IsArray) { if (ProcessScriptObject(iteratorObjects, folderName, script, parentNode)) { fileCount++; } } else { foreach (IScriptBaseObject iteratorObject in iteratorObjects) { if (iteratorObject != null && ProcessScriptObject(iteratorObject, folderName, script, parentNode)) { fileCount++; } } } } return(fileCount); }
private void ProcessFileGenerationException(ProjectFileTreeNode parentNode, int fileId, string fileName, BinaryFileInformation fileInfo, Exception ex) { var baseException = ex.GetBaseException(); string stackTrace = baseException.StackTrace; stackTrace = stackTrace.Substring(stackTrace.IndexOf(":line ") + ":line ".Length); int errLine = int.Parse(stackTrace); ArchAngel.Common.Generator.DebugPos debugPos = ArchAngel.Common.Generator.GetDebugPos(string.Format("StaticFile_{0}", fileId), errLine - 1, 1, string.Format("Error: {0}\nFileId: {1}.", baseException.Message, fileId)); string message = string.Format("<span class='error'>Line {0}: {1}</span>", errLine, baseException.Message); //if (ex.InnerException != null) //{ // message += ":<br/>" + Environment.NewLine + "<b>" + ex.InnerException.Message + "</b>" + // Environment.NewLine + GetCleanTemplateFunctionErrorStackTrace(ex) + // Environment.NewLine + "Target Site: " + ex.InnerException.TargetSite; //} //if (addToProjectFileTree) parentNode.AddChildNode(fileInfo, fileName).GenerationError = new GenerationError(fileName, message); NumFiles++; }
private void ProcessFile(ArchAngel.Interfaces.Template.File file, string path, ProjectFileTreeNode parentNode, object parentFolderIteratorObject) { string filePath; string relativeFilePath = null; string body; string fileName; TextFileInformation fileInfo; bool skipFile = false; switch (file.Iterator) { case ArchAngel.Interfaces.Template.IteratorTypes.None: try { fileName = GetFileName(file.Id, null); } catch (Exception ex) { fileName = "ERROR"; filePath = Utility.PathCombine(path, fileName); relativeFilePath = filePath.Replace(TargetFolder, "").TrimStart(Path.DirectorySeparatorChar); fileInfo = new TextFileInformation() { RelativeFilePath = relativeFilePath, NewGenFile = new TextFile(filePath, false), Encoding = file.Encoding }; ProcessFileGenerationException(parentNode, file.Id, fileName, fileInfo, ex); NumFiles++; return; } filePath = Utility.PathCombine(path, fileName); relativeFilePath = filePath.Replace(TargetFolder, "").TrimStart(Path.DirectorySeparatorChar); fileInfo = new TextFileInformation() { RelativeFilePath = relativeFilePath, NewGenFile = new TextFile(filePath, false), Encoding = file.Encoding }; try { CopyUserFileToGenerationLocation(filePath, fileInfo); CurrentFilePathProperty.SetValue(null, filePath, null); body = Utility.StandardizeLineBreaks(GetFileBody(file.Id, null, out skipFile), Utility.LineBreaks.Windows); string newFilePath = (string)CurrentFilePathProperty.GetValue(null, null); if (newFilePath != filePath) { //filePath = newFilePath; //relativeFilePath = filePath.Replace(TargetFolder, "").TrimStart(Path.DirectorySeparatorChar); fileInfo = new TextFileInformation() { RelativeFilePath = relativeFilePath, NewGenFile = new TextFile(filePath, false), Encoding = file.Encoding }; } } catch (Exception ex) { ProcessFileGenerationException(parentNode, file.Id, fileName, fileInfo, ex); return; } if (!skipFile) { Slyce.Common.Utility.DeleteFileBrute(filePath); System.IO.File.WriteAllText(filePath, body); parentNode.AddChildNode(fileInfo, fileName); AllTextFilenames.Add(new FilenameInfo(fileName, file.Name, file.Iterator, FilenameInfo.FilenameTypes.GeneratedFile) { RelativePath = relativeFilePath }); NumFiles++; } break; case ArchAngel.Interfaces.Template.IteratorTypes.Entity: List<ArchAngel.Interfaces.Scripting.NHibernate.Model.IEntity> entities = new List<Interfaces.Scripting.NHibernate.Model.IEntity>(); if (parentFolderIteratorObject == null) entities = ScriptProject.Entities; else if (parentFolderIteratorObject is Interfaces.Scripting.NHibernate.Model.IEntity) { entities = new List<Interfaces.Scripting.NHibernate.Model.IEntity>(); entities.Add((ArchAngel.Interfaces.Scripting.NHibernate.Model.IEntity)parentFolderIteratorObject); } else throw new InvalidDataException(string.Format("File iterator is 'Entity' but parent folder is '{0}'. Iterator can therefore only be: 'Entity', 'None'.", parentFolderIteratorObject.GetType().Name)); foreach (var entity in entities) { try { fileName = GetFileName(file.Id, entity); } catch (Exception ex) { fileName = GetNodeDisplayText(file.Name, string.Format("[{0}]", entity.Name)); filePath = Utility.PathCombine(path, fileName); relativeFilePath = filePath.Replace(TargetFolder, "").TrimStart(Path.DirectorySeparatorChar); fileInfo = new TextFileInformation() { RelativeFilePath = relativeFilePath, NewGenFile = new TextFile(filePath, false), Encoding = file.Encoding }; ProcessFileGenerationException(parentNode, file.Id, fileName, fileInfo, ex); NumFiles++; continue; } filePath = Utility.PathCombine(path, fileName); relativeFilePath = filePath.Replace(TargetFolder, "").TrimStart(Path.DirectorySeparatorChar); fileInfo = new TextFileInformation() { RelativeFilePath = relativeFilePath, NewGenFile = new TextFile(filePath, false), Encoding = file.Encoding }; try { CopyUserFileToGenerationLocation(filePath, fileInfo); CurrentFilePathProperty.SetValue(null, filePath, null); body = Utility.StandardizeLineBreaks(GetFileBody(file.Id, entity, out skipFile), Utility.LineBreaks.Windows); string newFilePath = (string)CurrentFilePathProperty.GetValue(null, null); if (newFilePath != filePath) { //filePath = newFilePath; //relativeFilePath = filePath.Replace(TargetFolder, "").TrimStart(Path.DirectorySeparatorChar); fileInfo = new TextFileInformation() { RelativeFilePath = relativeFilePath, NewGenFile = new TextFile(filePath, false), Encoding = file.Encoding }; } } catch (Exception ex) { ProcessFileGenerationException(parentNode, file.Id, fileName, fileInfo, ex); continue; } if (!skipFile) { Slyce.Common.Utility.DeleteFileBrute(filePath); System.IO.File.WriteAllText(filePath, body); parentNode.AddChildNode(fileInfo, fileName); AllTextFilenames.Add(new FilenameInfo(fileName, file.Name, file.Iterator, FilenameInfo.FilenameTypes.GeneratedFile) { RelativePath = relativeFilePath }); NumFiles++; } } break; case ArchAngel.Interfaces.Template.IteratorTypes.Component: foreach (var component in ScriptProject.Components) { try { fileName = GetFileName(file.Id, component); } catch (Exception ex) { fileName = "ERROR"; filePath = Utility.PathCombine(path, fileName); relativeFilePath = filePath.Replace(TargetFolder, "").TrimStart(Path.DirectorySeparatorChar); fileInfo = new TextFileInformation() { RelativeFilePath = relativeFilePath, NewGenFile = new TextFile(filePath, false), Encoding = file.Encoding }; ProcessFileGenerationException(parentNode, file.Id, fileName, fileInfo, ex); NumFiles++; continue; } filePath = Utility.PathCombine(path, fileName); relativeFilePath = filePath.Replace(TargetFolder, "").TrimStart(Path.DirectorySeparatorChar); fileInfo = new TextFileInformation() { RelativeFilePath = relativeFilePath, NewGenFile = new TextFile(filePath, false), Encoding = file.Encoding }; try { CopyUserFileToGenerationLocation(filePath, fileInfo); CurrentFilePathProperty.SetValue(null, filePath, null); body = Utility.StandardizeLineBreaks(GetFileBody(file.Id, component, out skipFile), Utility.LineBreaks.Windows); string newFilePath = (string)CurrentFilePathProperty.GetValue(null, null); if (newFilePath != filePath) { //filePath = newFilePath; //relativeFilePath = filePath.Replace(TargetFolder, "").TrimStart(Path.DirectorySeparatorChar); fileInfo = new TextFileInformation() { RelativeFilePath = relativeFilePath, NewGenFile = new TextFile(filePath, false), Encoding = file.Encoding }; } } catch (Exception ex) { ProcessFileGenerationException(parentNode, file.Id, fileName, fileInfo, ex); continue; } if (!skipFile) { Slyce.Common.Utility.DeleteFileBrute(filePath); System.IO.File.WriteAllText(filePath, body); parentNode.AddChildNode(fileInfo, fileName); AllTextFilenames.Add(new FilenameInfo(fileName, file.Name, file.Iterator, FilenameInfo.FilenameTypes.GeneratedFile) { RelativePath = relativeFilePath }); NumFiles++; } } break; case ArchAngel.Interfaces.Template.IteratorTypes.Table: List<ArchAngel.Interfaces.Scripting.NHibernate.Model.ITable> tables = new List<Interfaces.Scripting.NHibernate.Model.ITable>(); if (parentFolderIteratorObject == null) tables = ScriptProject.Tables; else if (parentFolderIteratorObject is Interfaces.Scripting.NHibernate.Model.ITable) { tables = new List<Interfaces.Scripting.NHibernate.Model.ITable>(); tables.Add((ArchAngel.Interfaces.Scripting.NHibernate.Model.ITable)parentFolderIteratorObject); } else throw new InvalidDataException(string.Format("File iterator is 'Table' but parent folder is '{0}'. Iterator can therefore only be: 'Table', 'None'.", parentFolderIteratorObject.GetType().Name)); foreach (var table in tables) { try { fileName = GetFileName(file.Id, table); } catch (Exception ex) { fileName = "ERROR"; filePath = Utility.PathCombine(path, fileName); relativeFilePath = filePath.Replace(TargetFolder, "").TrimStart(Path.DirectorySeparatorChar); fileInfo = new TextFileInformation() { RelativeFilePath = relativeFilePath, NewGenFile = new TextFile(filePath, false), Encoding = file.Encoding }; ProcessFileGenerationException(parentNode, file.Id, fileName, fileInfo, ex); NumFiles++; continue; } filePath = Utility.PathCombine(path, fileName); relativeFilePath = filePath.Replace(TargetFolder, "").TrimStart(Path.DirectorySeparatorChar); fileInfo = new TextFileInformation() { RelativeFilePath = relativeFilePath, NewGenFile = new TextFile(filePath, false), Encoding = file.Encoding }; try { CopyUserFileToGenerationLocation(filePath, fileInfo); CurrentFilePathProperty.SetValue(null, filePath, null); body = Utility.StandardizeLineBreaks(GetFileBody(file.Id, table, out skipFile), Utility.LineBreaks.Windows); string newFilePath = (string)CurrentFilePathProperty.GetValue(null, null); if (newFilePath != filePath) { //filePath = newFilePath; //relativeFilePath = filePath.Replace(TargetFolder, "").TrimStart(Path.DirectorySeparatorChar); fileInfo = new TextFileInformation() { RelativeFilePath = relativeFilePath, NewGenFile = new TextFile(filePath, false), Encoding = file.Encoding }; } } catch (Exception ex) { ProcessFileGenerationException(parentNode, file.Id, fileName, fileInfo, ex); continue; } if (!skipFile) { Slyce.Common.Utility.DeleteFileBrute(filePath); System.IO.File.WriteAllText(filePath, body); parentNode.AddChildNode(fileInfo, fileName); AllTextFilenames.Add(new FilenameInfo(fileName, file.Name, file.Iterator, FilenameInfo.FilenameTypes.GeneratedFile) { RelativePath = relativeFilePath }); NumFiles++; } } break; default: throw new NotImplementedException("This iterator not handled yet: " + file.Iterator.ToString()); } }
private void ProcessFileGenerationException(ProjectFileTreeNode parentNode, int fileId, string fileName, TextFileInformation fileInfo, Exception ex) { int line; string cleanStackTrace = GetCleanStackTrace(ex.InnerException.StackTrace, fileId, out line); string message = string.Format("<span class='filename'><b>Error Message:</b></span>{0}<span class='error'>{1}{0}{0}</span><span class='filename'><b>Stacktrace:</b></span>{0}<span class='error'>{2}</span>", "<br/> ", ex.InnerException.Message, cleanStackTrace); parentNode.AddChildNode(fileInfo, fileName).GenerationError = new GenerationError(fileName, message); NumFiles++; }
/// <summary> /// Adds the node to the list of nodes contained in this tree. /// </summary> /// <param name="node">The node that has been added to the tree.</param> protected override void AddNode(ProjectFileTreeNode node) { allNodes.Add(node); treeNodeCache[node.Path] = node; }
private void CreateFolder(Folder folder, string path, ProjectFileTreeNode parentNode, ref string folderPath, ref ProjectFileTreeNode folderNode, object iteratorObject) { string folderName = GetFolderName(folder.ID, iteratorObject); folderPath = Utility.PathCombine(path, folderName); if (!Directory.Exists(folderPath)) Directory.CreateDirectory(folderPath); folderNode = parentNode.AddChildNode(folderName); folderNode.IsFolder = true; foreach (Folder subFolder in folder.Folders) ProcessFolder(subFolder, folderPath, folderNode); foreach (ArchAngel.Interfaces.Template.File file in folder.Files) ProcessFile(file, folderPath, folderNode, iteratorObject); foreach (ArchAngel.Interfaces.Template.StaticFile staticFile in folder.StaticFiles) ProcessStaticFile(staticFile, folderPath, folderNode); }
public int WriteFiles( ProjectFileTreeNode parentNode, ArchAngel.Interfaces.Scripting.NHibernate.Model.IProject project, string targetFolder, ArchAngel.Interfaces.Template.TemplateProject templateProject, out List<FilenameInfo> duplicateFiles) { if (!Directory.Exists(targetFolder)) throw new FileNotFoundException("Output folder doesn't exist: " + targetFolder, targetFolder); //////////////////////////////////////// TargetFolder = targetFolder; SharedData.IsBusyGenerating = true; SharedData.CurrentProject.StartNewFileGenerationRun(); // Reset the Template before the File name validation run. _Loader.CallTemplateFunction(TemplateHelper.ClearTemplateCacheFunctionName); // Run the pre generation template function. var data = new PreGenerationData { OutputFolder = SharedData.CurrentProject.ProjectSettings.OutputPath, OverwriteFiles = SharedData.CurrentProject.ProjectSettings.OverwriteFiles }; foreach (var uo in SharedData.CurrentProject.Options.Where(o => o.IsVirtualProperty == false)) { var optionValue = SharedData.CurrentProject.GetUserOption(uo.VariableName); data.UserOptions.Add(uo.VariableName, optionValue); } foreach (var provider in SharedData.CurrentProject.Providers) { ArchAngel.Interfaces.ProviderInfo[] otherProviders = new ProviderInfo[SharedData.CurrentProject.Providers.Count]; SharedData.CurrentProject.Providers.CopyTo(otherProviders); data.OtherProviderInfos = otherProviders.ToList(); data.OtherProviderInfos.Remove(provider); _Loader.CallPreGenerationInitialisationFunction(provider, data); } ((ProjectFileTree)parentNode).TreeRestructuring = true; ((ProjectFileTree)parentNode).Clear(); ArchAngel.Interfaces.SharedData.CurrentProject.ScriptProject.OutputFolder = project.OutputFolder; ArchAngel.Interfaces.SharedData.CurrentProject.ScriptProject.TempFolder = project.TempFolder; ArchAngel.Interfaces.SharedData.CurrentProject.InitialiseScriptObjects(); SetProjectInCode(ArchAngel.Interfaces.SharedData.CurrentProject.ScriptProject); project = ArchAngel.Interfaces.SharedData.CurrentProject.ScriptProject; //SetProjectInCode(project); //////////////////////////////////////// // TODO: Check for duplicate files and folders ScriptProject = project; NumFiles = 0; //SkipFileProperty = CurrentAssembly.GetType("Slyce.FunctionRunner.FunctionProcessor").GetProperty("SkipCurrentFile"); foreach (Folder subFolder in templateProject.OutputFolder.Folders) ProcessFolder(subFolder, targetFolder, parentNode); foreach (ArchAngel.Interfaces.Template.File file in templateProject.OutputFolder.Files) ProcessFile(file, targetFolder, parentNode, null); foreach (ArchAngel.Interfaces.Template.StaticFile staticFile in templateProject.OutputFolder.StaticFiles) ProcessStaticFile(staticFile, targetFolder, parentNode); targetFolder += Path.DirectorySeparatorChar.ToString(); duplicateFiles = new List<FilenameInfo>(); foreach (var f in AllTextFilenames) f.RelativePath = f.RelativePath.Replace(targetFolder, ""); foreach (var group in AllTextFilenames.GroupBy(n => n.RelativePath).Where(g => g.Count() > 1)) duplicateFiles.AddRange(group.Select(g => g)); return NumFiles; }
private bool ProcessScriptObject(object scriptObject, string folderName, IScript script, ProjectFileTreeNode parentNode) { bool success = true; string scriptName = UpdateScriptName(scriptObject, script); string fileName = Path.Combine(folderName, scriptName); _Loader.SetGeneratedFileNameOnTemplate(Path.Combine(_Project.ProjectSettings.OutputPath, fileName)); if (scriptName.IndexOf("#") >= 0) { success = false; } if (success) { TextFileInformation fileInfo = new TextFileInformation(); fileInfo.RelativeFilePath = fileName; try { // Reset the SkipCurrentFile and CurrentFileName variable _Loader.CallTemplateFunction(TemplateHelper.ResetSkipCurrentFileFunctionName); _Loader.CallTemplateFunction(TemplateHelper.ResetCurrentFileNameFunctionName); // Call the script file function to get the file text body object[] parameters = new[] { scriptObject }; // Check whether we must skip the current file string templateOutput = (string)_Loader.CallTemplateFunction(script.ScriptName, ref parameters); if (_ProgressHelper.IsCancellationPending()) { return(false); } bool skipCurrentFile = (bool)_Loader.CallTemplateFunction(TemplateHelper.GetSkipCurrentFileFunctionName); if (!skipCurrentFile) { templateOutput = Utility.StandardizeLineBreaks(templateOutput, Utility.LineBreaks.Windows); string codeInsertionFilename = (string)_Loader.CallTemplateFunction(TemplateHelper.GetCurrentFileNameFunctionName); if (string.IsNullOrEmpty(codeInsertionFilename)) { string fullPath = Path.Combine(absoluteBasePath, fileName); _FileController.WriteAllText(fullPath, templateOutput); // The file has successfully been written - add it to the GeneratedFiles _Project.AddGeneratedFile(new GeneratedFile(script.FileName, fullPath, fileName, script.ScriptName, script.IteratorName)); // Set the NewGen text to point to that file. fileInfo.NewGenFile = new TextFile(fullPath, false); string versionNumberString = _Loader.GetAssemblyVersionNumber(); VersionNumber versionNumber; if (VersionNumber.TryParse(versionNumberString, out versionNumber)) { // Get the template language from the template function. string templateLanguageString = _Loader.GetTemplateFunctionLanguage(script.ScriptName); try { fileInfo.TemplateLanguage = SyntaxEditorHelper.LanguageEnumFromName(templateLanguageString); } catch (NotImplementedException) { fileInfo.TemplateLanguage = null; } } if (addToProjectFileTree) { parentNode.AddChildNode(fileInfo, scriptName); } } else { // Code insertions were performed. Need to update a node in the tree. // expand the path if (Path.IsPathRooted(codeInsertionFilename) == false) { codeInsertionFilename = RelativePaths.RelativeToAbsolutePath(absoluteBasePath, codeInsertionFilename); } codeInsertionFilename = _FileController.GetFullPath(codeInsertionFilename); // Get the relative path string relativeCodeInsertionFilename = RelativePaths.GetRelativePath(_Project.ProjectSettings.OutputPath, codeInsertionFilename); // If the file is not under the output path, then reset it to the full path if (relativeCodeInsertionFilename.StartsWith("..")) { relativeCodeInsertionFilename = codeInsertionFilename; // We need to add its folder as a root node of the tree if (!parentNode.IsTreeRoot) { parentNode = parentNode.ParentTree; } } fileInfo.RelativeFilePath = relativeCodeInsertionFilename; string relPathStart = "." + Path.DirectorySeparatorChar; if (fileInfo.RelativeFilePath.StartsWith(relPathStart)) { fileInfo.RelativeFilePath = fileInfo.RelativeFilePath.Substring(2); } if (addToProjectFileTree) { ProjectFileTree tree; if (!parentNode.IsTreeRoot) { tree = parentNode.ParentTree; } else { tree = (ProjectFileTree)parentNode; } var possibleNode = tree.GetNodeAtPath(codeInsertionFilename); if (possibleNode == null) { // Need to create this node. // Create the node and it's parent folders if need be var node = tree.CreateFileNodeForPath(relativeCodeInsertionFilename); node.AssociatedFile = fileInfo; } else { // Update the NewGen text, don't add it to the generated files list. fileInfo = possibleNode.AssociatedFile as TextFileInformation; if (fileInfo == null) { throw new NotSupportedException("Cannot code merge a binary file"); } } } else { // Write the file to disk _FileController.WriteAllText(codeInsertionFilename, templateOutput); } fileInfo.NewGenFile = new TextFile(templateOutput); } AddFileCountToPreviousEventAndRefire(_ProgressHelper, 1); } } catch (TemplateFunctionException ex) { success = false; string message = "<span class='error'>" + ex.Message + "</span>"; if (ex.InnerException != null) { message += ":<br/>" + Environment.NewLine + "<b>" + ex.InnerException.Message + "</b>" + Environment.NewLine + GetCleanTemplateFunctionErrorStackTrace(ex) + Environment.NewLine + "Target Site: " + ex.InnerException.TargetSite; } RaiseTemplateFunctionCallErrorEvent(ex); // Do nothing, just skip the file because the error will get reported to the user. if (addToProjectFileTree) { parentNode.AddChildNode(fileInfo, scriptName).GenerationError = new GenerationError(fileName, message); } } catch (Exception ex) { string message = "<span class='error'>" + ex.Message + "</span>"; if (ex.InnerException != null) { message += ":<br/>" + Environment.NewLine + "<b>" + ex.InnerException.Message + "</b>" + Environment.NewLine + GetCleanTemplateFunctionErrorStackTrace(ex) + Environment.NewLine + "Target Site: " + ex.InnerException.TargetSite; } if (addToProjectFileTree) { parentNode.AddChildNode(fileInfo, scriptName).GenerationError = new GenerationError(fileName, message); } // Make sure any other type of exception gets thrown throw; } } return(success); }
/// <summary> /// Does a depth first search and returns the first node that satisfies the SearchCondition. /// </summary> /// <param name="node"></param> /// <param name="condition"></param> /// <returns></returns> public static ProjectFileTreeNode DepthFirstSearch(ProjectFileTreeNode node, ProjectFileSearchCondition condition) { if (condition.Satisfied(node)) return node; foreach (ProjectFileTreeNode childNode in node.ChildNodes) { ProjectFileTreeNode result = DepthFirstSearch(childNode, condition); if (result != null) return result; } return null; }
public int GenerateAllFiles(string folderName, IFolder folder, ProjectFileTreeNode parentNode, IScriptBaseObject thisLevelRootObject, string basePath, bool isTopLevel) { if (isTopLevel) { SharedData.IsBusyGenerating = true; _Project.StartNewFileGenerationRun(); // Reset the Template before the File name validation run. _Loader.CallTemplateFunction(TemplateHelper.ClearTemplateCacheFunctionName); // Run the pre generation template function. //var data = new PreGenerationData { OutputFolder = _Project.ProjectSettings.OutputPath }; //foreach (var uo in _Project.Options.Where(o => o.IsVirtualProperty == false)) //{ // var optionValue = _Loader.GetUserOption(uo.VariableName); // data.UserOptions.Add(uo.VariableName, optionValue); //} //foreach (var provider in _Project.Providers) //{ // ArchAngel.Interfaces.ProviderInfo[] otherProviders = new ProviderInfo[_Project.Providers.Count]; // _Project.Providers.CopyTo(otherProviders); // data.OtherProviderInfos = otherProviders.ToList(); // data.OtherProviderInfos.Remove(provider); // provider.InitialisePreGeneration(data); // //_Loader.CallPreGenerationInitialisationFunction(provider, data); //} IEnumerable <FilenameInfo> duplicates; DuplicateFileNameChecker checker = new DuplicateFileNameChecker(this, _Project, _Project.ProjectSettings.OutputPath); bool validates = checker.ValidateFileNames(folderName, folder, thisLevelRootObject, out duplicates); if (validates == false) { _ProgressHelper.ReportProgress(100, new GenerateFilesProgress(0, new DuplicateFilesException(duplicates))); return(0); } // Reset the Template again before the real template run. object[] parameters = new object[0]; _Loader.CallTemplateFunction(TemplateHelper.ClearTemplateCacheFunctionName, ref parameters); //foreach (var provider in _Project.Providers) //{ // _Loader.CallPreGenerationInitialisationFunction(provider, data); //} } if (parentNode == null && isTopLevel) { addToProjectFileTree = false; } if (_Loader == null) { return(0); } if (addToProjectFileTree && parentNode is ProjectFileTree) { ((ProjectFileTree)parentNode).TreeRestructuring = true; ((ProjectFileTree)parentNode).Clear(); } int fileCount = 0; try { CurrentRootObject = thisLevelRootObject; absoluteBasePath = basePath; { Version version = new Version(_Loader.GetAssemblyVersionNumber()); Version expectedVersion = new Version(1, 1, 9, 49); if (version < expectedVersion) { throw new OldVersionException("The template was compiled with an old version of ArchAngel, and cannot be used in this version of Workbench"); } } foreach (IFolder subFolder in folder.SubFolders) { if (_ProgressHelper.IsCancellationPending()) { _ProgressHelper.Cancel(); return(fileCount); } ProjectFileTreeNode folderNode = null; if (addToProjectFileTree && parentNode != null && subFolder.Name != "ROOT") { folderNode = parentNode.AddChildNode(subFolder.Name); folderNode.IsFolder = true; } if (!string.IsNullOrEmpty(subFolder.IteratorName)) { // The folder has an iterator ProviderInfo provider; Type iteratorType = _Project.GetIteratorTypeFromProviders(subFolder.IteratorName, out provider); if (_ProgressHelper.IsCancellationPending()) { _ProgressHelper.Cancel(); return(fileCount); } object[] iteratorObjects; if (thisLevelRootObject == null) { iteratorObjects = provider.GetAllObjectsOfType(iteratorType.FullName).ToArray(); } else if (iteratorType.IsInstanceOfType(thisLevelRootObject)) { iteratorObjects = new[] { thisLevelRootObject }; } else { iteratorObjects = provider.GetAllObjectsOfType(iteratorType.FullName, thisLevelRootObject).ToArray(); } if (iteratorObjects != null) { foreach (IScriptBaseObject iteratorObject in iteratorObjects) { if (_ProgressHelper.IsCancellationPending()) { _ProgressHelper.Cancel(); return(fileCount); } CurrentRootObject = iteratorObject; string subFolderName = UpdateScriptName(iteratorObject, subFolder); if (folderNode != null) { folderNode.Text = subFolderName; } subFolderName = Path.Combine(folderName, subFolderName); fileCount += GenerateAllFiles(subFolderName, subFolder, folderNode, CurrentRootObject, basePath, false); } } } else { // The folder doesn't have an iterator if (_ProgressHelper.IsCancellationPending()) { _ProgressHelper.Cancel(); return(fileCount); } string subFolderName = UpdateScriptName(null, subFolder); if (folderNode != null) { folderNode.Text = subFolderName; } subFolderName = Path.Combine(folderName, subFolderName); fileCount += GenerateAllFiles(subFolderName, subFolder, folderNode, thisLevelRootObject, basePath, false); } } foreach (IScript script in folder.Scripts) { if (_ProgressHelper.IsCancellationPending()) { _ProgressHelper.Cancel(); return(fileCount); } fileCount += CreateScriptFile(folderName, script, parentNode); } foreach (IFile file in folder.Files) { if (_ProgressHelper.IsCancellationPending()) { _ProgressHelper.Cancel(); return(fileCount); } fileCount += CreateStaticFile(folderName, file, parentNode); } } catch (Exception e) { _ProgressHelper.ReportProgress(100, new GenerateFilesProgress(fileCount, e)); return(fileCount); } finally { if (addToProjectFileTree && parentNode is ProjectFileTree) { ((ProjectFileTree)parentNode).TreeRestructuring = false; parentNode.RaiseNodeChangedEvent(parentNode, true); } } if (isTopLevel) { SharedData.IsBusyGenerating = false; } _ProgressHelper.ReportProgress(50, new GenerateFilesProgress(fileCount)); return(fileCount); }
internal ProjectFileTreeNode(ProjectFileTreeNode parentNode, ProjectFileTree parentTree) { this.parentNode = parentNode; this.parentTree = parentTree; }
/// <summary> /// /// </summary> /// <param name="childrenChanged">Whether the children of this node also changed.</param> /// <param name="changedNode">The node that changed.</param> public ProjectFileTreeChangedEventArgs(ProjectFileTreeNode changedNode, bool childrenChanged) { this.childrenChanged = childrenChanged; this.changedNode = changedNode; }
public bool Satisfied(ProjectFileTreeNode node) { return(node.IsFolder == false && node.ChildNodes.Count == 0); }
private void ProcessFolder(Folder folder, string path, ProjectFileTreeNode parentNode) { string folderPath = ""; ProjectFileTreeNode folderNode = null; switch (folder.Iterator) { case ArchAngel.Interfaces.Template.IteratorTypes.None: CreateFolder(folder, path, parentNode, ref folderPath, ref folderNode, null); break; case ArchAngel.Interfaces.Template.IteratorTypes.Entity: foreach (var entity in ScriptProject.Entities) CreateFolder(folder, path, parentNode, ref folderPath, ref folderNode, entity); break; case ArchAngel.Interfaces.Template.IteratorTypes.Table: foreach (var table in ScriptProject.Tables) CreateFolder(folder, path, parentNode, ref folderPath, ref folderNode, table); break; case ArchAngel.Interfaces.Template.IteratorTypes.Column: foreach (var column in ScriptProject.Tables.Select(t => t.Columns)) CreateFolder(folder, path, parentNode, ref folderPath, ref folderNode, column); break; case ArchAngel.Interfaces.Template.IteratorTypes.Component: foreach (var component in ScriptProject.Components) CreateFolder(folder, path, parentNode, ref folderPath, ref folderNode, component); break; default: throw new NotImplementedException("This iterator not handled yet: " + folder.Iterator.ToString()); } }
private void ProcessStaticFile(ArchAngel.Interfaces.Template.StaticFile staticFile, string path, ProjectFileTreeNode parentNode) { string filePath; string relativeFilePath; string fileName; BinaryFileInformation fileInfo; bool skipFile = false; switch (staticFile.Iterator) { case ArchAngel.Interfaces.Template.IteratorTypes.None: try { fileName = GetStaticFileName(staticFile.Id, null); } catch (Exception ex) { fileName = "ERROR"; filePath = Utility.PathCombine(path, fileName); relativeFilePath = filePath.Replace(TargetFolder, "").TrimStart(Path.DirectorySeparatorChar); fileInfo = new BinaryFileInformation() { RelativeFilePath = relativeFilePath, NewGenFile = new BinaryFile(filePath, false) }; ProcessFileGenerationException(parentNode, staticFile.Id, fileName, fileInfo, ex); NumFiles++; return; } filePath = Utility.PathCombine(path, fileName); relativeFilePath = filePath.Replace(TargetFolder, "").TrimStart(Path.DirectorySeparatorChar); fileInfo = new BinaryFileInformation() { RelativeFilePath = relativeFilePath, NewGenFile = new BinaryFile(filePath, false) }; try { CopyUserFileToGenerationLocation(filePath, fileInfo); CurrentFilePathProperty.SetValue(null, filePath, null); CallStaticFilePreWriteFunction(staticFile.Id, null, out skipFile); string newFilePath = (string)CurrentFilePathProperty.GetValue(null, null); if (newFilePath != filePath) { //filePath = newFilePath; relativeFilePath = filePath.Replace(TargetFolder, "").TrimStart(Path.DirectorySeparatorChar); fileInfo = new BinaryFileInformation() { RelativeFilePath = relativeFilePath, NewGenFile = new BinaryFile(filePath, false) }; } } catch (Exception ex) { ProcessFileGenerationException(parentNode, staticFile.Id, fileName, fileInfo, ex); return; } if (!skipFile) { string fromFile = Utility.PathCombine(ArchAngel.Interfaces.SharedData.CurrentProject.TemplateProject.ResourceFilesFolder, staticFile.ResourceName); if (System.IO.File.Exists(filePath)) Slyce.Common.Utility.DeleteFileBrute(filePath); System.IO.File.Copy(fromFile, filePath); parentNode.AddChildNode(fileInfo, fileName); AllTextFilenames.Add(new FilenameInfo(fileName, staticFile.Name, staticFile.Iterator, FilenameInfo.FilenameTypes.StaticFile) { RelativePath = relativeFilePath }); NumFiles++; } break; case ArchAngel.Interfaces.Template.IteratorTypes.Entity: foreach (var entity in ScriptProject.Entities) { try { fileName = GetStaticFileName(staticFile.Id, entity); } catch (Exception ex) { fileName = GetNodeDisplayText(staticFile.Name, string.Format("[{0}]", entity.Name)); filePath = Utility.PathCombine(path, fileName); relativeFilePath = filePath.Replace(TargetFolder, "").TrimStart(Path.DirectorySeparatorChar); fileInfo = new BinaryFileInformation() { RelativeFilePath = relativeFilePath, NewGenFile = new BinaryFile(filePath, false) }; ProcessFileGenerationException(parentNode, staticFile.Id, fileName, fileInfo, ex); NumFiles++; continue; } filePath = Utility.PathCombine(path, fileName); relativeFilePath = filePath.Replace(TargetFolder, "").TrimStart(Path.DirectorySeparatorChar); fileInfo = new BinaryFileInformation() { RelativeFilePath = relativeFilePath, NewGenFile = new BinaryFile(filePath, false) }; try { CopyUserFileToGenerationLocation(filePath, fileInfo); CurrentFilePathProperty.SetValue(null, filePath, null); CallStaticFilePreWriteFunction(staticFile.Id, entity, out skipFile); string newFilePath = (string)CurrentFilePathProperty.GetValue(null, null); if (newFilePath != filePath) { //filePath = newFilePath; relativeFilePath = filePath.Replace(TargetFolder, "").TrimStart(Path.DirectorySeparatorChar); fileInfo = new BinaryFileInformation() { RelativeFilePath = relativeFilePath, NewGenFile = new BinaryFile(filePath, false) }; } } catch (Exception ex) { ProcessFileGenerationException(parentNode, staticFile.Id, fileName, fileInfo, ex); continue; } if (!skipFile) { System.IO.File.Copy(staticFile.ResourceName, filePath); parentNode.AddChildNode(fileInfo, fileName); AllTextFilenames.Add(new FilenameInfo(fileName, staticFile.Name, staticFile.Iterator, FilenameInfo.FilenameTypes.GeneratedFile) { RelativePath = relativeFilePath }); NumFiles++; } } break; case ArchAngel.Interfaces.Template.IteratorTypes.Component: foreach (var component in ScriptProject.Components) { try { fileName = GetStaticFileName(staticFile.Id, component); } catch (Exception ex) { fileName = "ERROR"; filePath = Utility.PathCombine(path, fileName); relativeFilePath = filePath.Replace(TargetFolder, "").TrimStart(Path.DirectorySeparatorChar); fileInfo = new BinaryFileInformation() { RelativeFilePath = relativeFilePath, NewGenFile = new BinaryFile(filePath, false) }; ProcessFileGenerationException(parentNode, staticFile.Id, fileName, fileInfo, ex); NumFiles++; continue; } filePath = Utility.PathCombine(path, fileName); relativeFilePath = filePath.Replace(TargetFolder, "").TrimStart(Path.DirectorySeparatorChar); fileInfo = new BinaryFileInformation() { RelativeFilePath = relativeFilePath, NewGenFile = new BinaryFile(filePath, false) }; try { CopyUserFileToGenerationLocation(filePath, fileInfo); CurrentFilePathProperty.SetValue(null, filePath, null); CallStaticFilePreWriteFunction(staticFile.Id, component, out skipFile); string newFilePath = (string)CurrentFilePathProperty.GetValue(null, null); if (newFilePath != filePath) { //filePath = newFilePath; relativeFilePath = filePath.Replace(TargetFolder, "").TrimStart(Path.DirectorySeparatorChar); fileInfo = new BinaryFileInformation() { RelativeFilePath = relativeFilePath, NewGenFile = new BinaryFile(filePath, false) }; } } catch (Exception ex) { ProcessFileGenerationException(parentNode, staticFile.Id, fileName, fileInfo, ex); continue; } if (!skipFile) { System.IO.File.Copy(staticFile.ResourceName, filePath); parentNode.AddChildNode(fileInfo, fileName); AllTextFilenames.Add(new FilenameInfo(fileName, staticFile.Name, staticFile.Iterator, FilenameInfo.FilenameTypes.GeneratedFile) { RelativePath = relativeFilePath }); NumFiles++; } } break; case ArchAngel.Interfaces.Template.IteratorTypes.Table: foreach (var table in ScriptProject.Tables) { try { fileName = GetStaticFileName(staticFile.Id, table); } catch (Exception ex) { fileName = "ERROR"; filePath = Utility.PathCombine(path, fileName); relativeFilePath = filePath.Replace(TargetFolder, "").TrimStart(Path.DirectorySeparatorChar); fileInfo = new BinaryFileInformation() { RelativeFilePath = relativeFilePath, NewGenFile = new BinaryFile(filePath, false) }; ProcessFileGenerationException(parentNode, staticFile.Id, fileName, fileInfo, ex); NumFiles++; continue; } filePath = Utility.PathCombine(path, fileName); relativeFilePath = filePath.Replace(TargetFolder, "").TrimStart(Path.DirectorySeparatorChar); fileInfo = new BinaryFileInformation() { RelativeFilePath = relativeFilePath, NewGenFile = new BinaryFile(filePath, false) }; try { CopyUserFileToGenerationLocation(filePath, fileInfo); CurrentFilePathProperty.SetValue(null, filePath, null); CallStaticFilePreWriteFunction(staticFile.Id, table, out skipFile); string newFilePath = (string)CurrentFilePathProperty.GetValue(null, null); if (newFilePath != filePath) { //filePath = newFilePath; relativeFilePath = filePath.Replace(TargetFolder, "").TrimStart(Path.DirectorySeparatorChar); fileInfo = new BinaryFileInformation() { RelativeFilePath = relativeFilePath, NewGenFile = new BinaryFile(filePath, false) }; } } catch (Exception ex) { ProcessFileGenerationException(parentNode, staticFile.Id, fileName, fileInfo, ex); continue; } if (!skipFile) { System.IO.File.Copy(staticFile.ResourceName, filePath); parentNode.AddChildNode(fileInfo, fileName); AllTextFilenames.Add(new FilenameInfo(fileName, staticFile.Name, staticFile.Iterator, FilenameInfo.FilenameTypes.GeneratedFile) { RelativePath = relativeFilePath }); NumFiles++; } } break; default: throw new NotImplementedException("This iterator not handled yet: " + staticFile.Iterator.ToString()); } }
/// <summary> /// Runs through a project and generates the files in it. /// </summary> /// <param name="folderName">The name of the root folder to generate into. Not the full path, just the relative path to the /// current folder.</param> /// <param name="folder"></param> /// <param name="parentNode">If this is null, the files will just be generated, not </param> /// <param name="thisLevelRootObject"></param> /// <returns></returns> /// <param name="basePath">The path to which the files should be generated</param> public int GenerateAllFiles(string folderName, IFolder folder, ProjectFileTreeNode parentNode, IScriptBaseObject thisLevelRootObject, string basePath) { return(GenerateAllFiles(folderName, folder, parentNode, thisLevelRootObject, basePath, true)); }
/// <summary> /// Creates the static files and writes them to the Workbench_FileGenerator component directory. /// </summary> /// <param name="folderName">The relative path of the folder this file will be placed in.</param> /// <param name="file"></param> /// <param name="parentNode"></param> /// <returns>The number of files created.</returns> private int CreateStaticFile(string folderName, IFile file, ProjectFileTreeNode parentNode) { int fileCount = 0; if (string.IsNullOrEmpty(file.IteratorName)) { fileCount++; string fileName = UpdateScriptName(null, file); string relativeFilePath = Path.Combine(folderName, fileName); string fullPath = Path.Combine(absoluteBasePath, relativeFilePath); if (GetSkipCurrentFile(file, Path.Combine(_Project.ProjectSettings.OutputPath, relativeFilePath))) { return(fileCount); } _FileController.WriteResourceToFile(_Loader.CurrentAssembly, file.StaticFileName, fullPath); _Project.AddGeneratedFile(new GeneratedFile(file.Name, fullPath, relativeFilePath, "", file.IteratorName)); if (addToProjectFileTree) { BinaryFile outFile = new BinaryFile(fullPath, false); BinaryFileInformation binFileInfo = new BinaryFileInformation(); binFileInfo.NewGenFile = outFile; binFileInfo.RelativeFilePath = relativeFilePath; parentNode.AddChildNode(binFileInfo, fileName); } AddFileCountToPreviousEventAndRefire(_ProgressHelper, 1); return(fileCount); } ProviderInfo provider; Type iteratorType = _Project.GetIteratorTypeFromProviders(file.IteratorName, out provider); IScriptBaseObject[] iteratorObjects = GetIteratorObjects(iteratorType, provider); if (iteratorObjects != null) { if (iteratorType.IsArray) { throw new NotImplementedException("Array iterator types not handled for static files yet. Please inform [email protected] about this error."); } foreach (IScriptBaseObject iteratorObject in iteratorObjects) { string fileName = UpdateScriptName(iteratorObject, file); string relativeFilePath = Path.Combine(folderName, fileName); string fullPath = Path.Combine(absoluteBasePath, relativeFilePath); if (GetSkipCurrentFile(file, Path.Combine(_Project.ProjectSettings.OutputPath, relativeFilePath))) { // Skip the file. continue; } _FileController.WriteResourceToFile(_Loader.CurrentAssembly, file.StaticFileName, fullPath); _Project.AddGeneratedFile(new GeneratedFile(file.Name, fullPath, relativeFilePath, "", file.IteratorName)); if (addToProjectFileTree) { BinaryFile outFile = new BinaryFile(fullPath, false); BinaryFileInformation binFileInfo = new BinaryFileInformation(); binFileInfo.RelativeFilePath = relativeFilePath; binFileInfo.NewGenFile = outFile; parentNode.AddChildNode(binFileInfo, fileName); } fileCount++; AddFileCountToPreviousEventAndRefire(_ProgressHelper, 1); } } return(fileCount); }
/// <summary> /// Override this in the Tree class to provide a method of adding nodes to a collection of all nodes. /// </summary> /// <param name="node">The node to add.</param> /// <exception cref="InvalidOperationException">Thrown if the base version of this method is called. It must be overridden.</exception> protected virtual void AddNode(ProjectFileTreeNode node) { throw new InvalidOperationException("Cannot call this on a node, must be called on the root Tree."); }
public void LoadCheckedStatusFromXml(XmlDocument xmlDocument) { XmlNodeList nodes = xmlDocument.GetElementsByTagName("Options"); if (nodes.Count != 1) { throw new ArgumentException("The given XmlDocument is not a valid CheckedStatus file."); } XmlElement rootNode = nodes[0] as XmlElement; if (rootNode == null) { throw new ArgumentException("The given XmlDocument is not a valid CheckedStatus file."); } nodes = rootNode.GetElementsByTagName("CheckedFiles"); if (nodes.Count != 1) { throw new ArgumentException("The given XmlDocument is not a valid CheckedStatus file."); } XmlElement checkedFilesNode = nodes[0] as XmlElement; if (checkedFilesNode == null) { throw new ArgumentException("The given XmlDocument is not a valid CheckedStatus file."); } nodes = checkedFilesNode.GetElementsByTagName("File"); TreeRestructuring = true; foreach (XmlNode node in nodes) { string relativePath = node.InnerText; ProjectFileTreeNode treeNode = GetNodeAtPath(relativePath); if (treeNode == null) { continue; } bool checkedStatus; try { checkedStatus = bool.Parse(node.Attributes["checked"].Value); } catch { checkedStatus = true; } treeNode.SetSingleNodeSelected(checkedStatus); if (treeNode.AssociatedFile == null) { continue; } if (node.Attributes["intellimerge"] != null) { if (rootNode.Attributes["version"] == null) { bool overwriteStatus; try { overwriteStatus = bool.Parse(node.Attributes["intellimerge"].Value); } catch { overwriteStatus = true; } treeNode.AssociatedFile.IntelliMerge = overwriteStatus ? IntelliMergeType.Overwrite : IntelliMergeType.AutoDetect; } else { int version = int.Parse(rootNode.Attributes["version"].Value); if (version == 1 && node.Attributes["intellimerge"] != null) { IntelliMergeType mergeType = (IntelliMergeType)Enum.Parse(typeof(IntelliMergeType), node.Attributes["intellimerge"].Value, true); treeNode.AssociatedFile.IntelliMerge = mergeType; } } } } TreeRestructuring = false; }
/// <summary> /// Runs through a project and generates the files in it. /// </summary> /// <param name="folderName">The name of the root folder to generate into. Not the full path, just the relative path to the /// current folder.</param> /// <param name="folder"></param> /// <param name="parentNode">If this is null, the files will just be generated, not </param> /// <param name="thisLevelRootObject"></param> /// <returns></returns> /// <param name="basePath">The path to which the files should be generated</param> public int GenerateAllFiles(string folderName, IFolder folder, ProjectFileTreeNode parentNode, IScriptBaseObject thisLevelRootObject, string basePath) { return GenerateAllFiles(folderName, folder, parentNode, thisLevelRootObject, basePath, true); }
public int GenerateAllFiles(string folderName, IFolder folder, ProjectFileTreeNode parentNode, IScriptBaseObject thisLevelRootObject, string basePath, bool isTopLevel) { if (isTopLevel) { SharedData.IsBusyGenerating = true; _Project.StartNewFileGenerationRun(); // Reset the Template before the File name validation run. _Loader.CallTemplateFunction(TemplateHelper.ClearTemplateCacheFunctionName); // Run the pre generation template function. //var data = new PreGenerationData { OutputFolder = _Project.ProjectSettings.OutputPath }; //foreach (var uo in _Project.Options.Where(o => o.IsVirtualProperty == false)) //{ // var optionValue = _Loader.GetUserOption(uo.VariableName); // data.UserOptions.Add(uo.VariableName, optionValue); //} //foreach (var provider in _Project.Providers) //{ // ArchAngel.Interfaces.ProviderInfo[] otherProviders = new ProviderInfo[_Project.Providers.Count]; // _Project.Providers.CopyTo(otherProviders); // data.OtherProviderInfos = otherProviders.ToList(); // data.OtherProviderInfos.Remove(provider); // provider.InitialisePreGeneration(data); // //_Loader.CallPreGenerationInitialisationFunction(provider, data); //} IEnumerable<FilenameInfo> duplicates; DuplicateFileNameChecker checker = new DuplicateFileNameChecker(this, _Project, _Project.ProjectSettings.OutputPath); bool validates = checker.ValidateFileNames(folderName, folder, thisLevelRootObject, out duplicates); if (validates == false) { _ProgressHelper.ReportProgress(100, new GenerateFilesProgress(0, new DuplicateFilesException(duplicates))); return 0; } // Reset the Template again before the real template run. object[] parameters = new object[0]; _Loader.CallTemplateFunction(TemplateHelper.ClearTemplateCacheFunctionName, ref parameters); //foreach (var provider in _Project.Providers) //{ // _Loader.CallPreGenerationInitialisationFunction(provider, data); //} } if (parentNode == null && isTopLevel) addToProjectFileTree = false; if (_Loader == null) return 0; if (addToProjectFileTree && parentNode is ProjectFileTree) { ((ProjectFileTree)parentNode).TreeRestructuring = true; ((ProjectFileTree)parentNode).Clear(); } int fileCount = 0; try { CurrentRootObject = thisLevelRootObject; absoluteBasePath = basePath; { Version version = new Version(_Loader.GetAssemblyVersionNumber()); Version expectedVersion = new Version(1, 1, 9, 49); if (version < expectedVersion) { throw new OldVersionException("The template was compiled with an old version of ArchAngel, and cannot be used in this version of Workbench"); } } foreach (IFolder subFolder in folder.SubFolders) { if (_ProgressHelper.IsCancellationPending()) { _ProgressHelper.Cancel(); return fileCount; } ProjectFileTreeNode folderNode = null; if (addToProjectFileTree && parentNode != null && subFolder.Name != "ROOT") { folderNode = parentNode.AddChildNode(subFolder.Name); folderNode.IsFolder = true; } if (!string.IsNullOrEmpty(subFolder.IteratorName)) { // The folder has an iterator ProviderInfo provider; Type iteratorType = _Project.GetIteratorTypeFromProviders(subFolder.IteratorName, out provider); if (_ProgressHelper.IsCancellationPending()) { _ProgressHelper.Cancel(); return fileCount; } object[] iteratorObjects; if (thisLevelRootObject == null) { iteratorObjects = provider.GetAllObjectsOfType(iteratorType.FullName).ToArray(); } else if (iteratorType.IsInstanceOfType(thisLevelRootObject)) { iteratorObjects = new[] { thisLevelRootObject }; } else { iteratorObjects = provider.GetAllObjectsOfType(iteratorType.FullName, thisLevelRootObject).ToArray(); } if (iteratorObjects != null) { foreach (IScriptBaseObject iteratorObject in iteratorObjects) { if (_ProgressHelper.IsCancellationPending()) { _ProgressHelper.Cancel(); return fileCount; } CurrentRootObject = iteratorObject; string subFolderName = UpdateScriptName(iteratorObject, subFolder); if (folderNode != null) { folderNode.Text = subFolderName; } subFolderName = Path.Combine(folderName, subFolderName); fileCount += GenerateAllFiles(subFolderName, subFolder, folderNode, CurrentRootObject, basePath, false); } } } else { // The folder doesn't have an iterator if (_ProgressHelper.IsCancellationPending()) { _ProgressHelper.Cancel(); return fileCount; } string subFolderName = UpdateScriptName(null, subFolder); if (folderNode != null) { folderNode.Text = subFolderName; } subFolderName = Path.Combine(folderName, subFolderName); fileCount += GenerateAllFiles(subFolderName, subFolder, folderNode, thisLevelRootObject, basePath, false); } } foreach (IScript script in folder.Scripts) { if (_ProgressHelper.IsCancellationPending()) { _ProgressHelper.Cancel(); return fileCount; } fileCount += CreateScriptFile(folderName, script, parentNode); } foreach (IFile file in folder.Files) { if (_ProgressHelper.IsCancellationPending()) { _ProgressHelper.Cancel(); return fileCount; } fileCount += CreateStaticFile(folderName, file, parentNode); } } catch (Exception e) { _ProgressHelper.ReportProgress(100, new GenerateFilesProgress(fileCount, e)); return fileCount; } finally { if (addToProjectFileTree && parentNode is ProjectFileTree) { ((ProjectFileTree)parentNode).TreeRestructuring = false; parentNode.RaiseNodeChangedEvent(parentNode, true); } } if (isTopLevel) SharedData.IsBusyGenerating = false; _ProgressHelper.ReportProgress(50, new GenerateFilesProgress(fileCount)); return fileCount; }
private static void LoadMD5sForNode(ProjectFileTreeNode node, string dir) { if (node.IsFolder == false) return; string manifestFile = System.IO.Path.Combine(dir, ManifestConstants.MANIFEST_FILENAME); if (File.Exists(manifestFile) == false) { return; } XmlDocument doc = new XmlDocument(); try { doc.Load(manifestFile); } catch (Exception) { return; } foreach (ProjectFileTreeNode childNode in node.ChildNodes) { if (childNode.AssociatedFile != null) { string userMD5, templateMD5, prevgenMD5; PrevGenUtility.GetMD5sForFile(doc, System.IO.Path.GetFileName(childNode.Path), out prevgenMD5, out templateMD5, out userMD5); childNode.AssociatedFile.SetPreviousVersionMD5s(prevgenMD5, templateMD5, userMD5); } else if (childNode.IsFolder) { LoadMD5sForNode(childNode, System.IO.Path.Combine(dir, childNode.Text)); } } }
/// <summary> /// Creates the actual files, or returns a count of the number of files that will be created, depending on value of createFiles. /// </summary> /// <param name="folderName"></param> /// <param name="script"></param> /// <param name="parentNode"></param> /// <returns></returns> private int CreateScriptFile(string folderName, IScript script, ProjectFileTreeNode parentNode) { int fileCount = 0; if (string.IsNullOrEmpty(script.IteratorName)) { if (ProcessScriptObject(null, folderName, script, parentNode)) { fileCount++; } return fileCount; } ProviderInfo provider; Type iteratorType = _Project.GetIteratorTypeFromProviders(script.IteratorName, out provider); IScriptBaseObject[] iteratorObjects = GetIteratorObjects(iteratorType, provider); if (iteratorObjects != null) { if (iteratorType.IsArray) { if (ProcessScriptObject(iteratorObjects, folderName, script, parentNode)) { fileCount++; } } else { foreach (IScriptBaseObject iteratorObject in iteratorObjects) { if (iteratorObject != null && ProcessScriptObject(iteratorObject, folderName, script, parentNode)) { fileCount++; } } } } return fileCount; }
public bool Satisfied(ProjectFileTreeNode node) { return node.IsFolder == false && node.ChildNodes.Count == 0; }
/// <summary> /// Creates the static files and writes them to the Workbench_FileGenerator component directory. /// </summary> /// <param name="folderName">The relative path of the folder this file will be placed in.</param> /// <param name="file"></param> /// <param name="parentNode"></param> /// <returns>The number of files created.</returns> private int CreateStaticFile(string folderName, IFile file, ProjectFileTreeNode parentNode) { int fileCount = 0; if (string.IsNullOrEmpty(file.IteratorName)) { fileCount++; string fileName = UpdateScriptName(null, file); string relativeFilePath = Path.Combine(folderName, fileName); string fullPath = Path.Combine(absoluteBasePath, relativeFilePath); if (GetSkipCurrentFile(file, Path.Combine(_Project.ProjectSettings.OutputPath, relativeFilePath))) { return fileCount; } _FileController.WriteResourceToFile(_Loader.CurrentAssembly, file.StaticFileName, fullPath); _Project.AddGeneratedFile(new GeneratedFile(file.Name, fullPath, relativeFilePath, "", file.IteratorName)); if (addToProjectFileTree) { BinaryFile outFile = new BinaryFile(fullPath, false); BinaryFileInformation binFileInfo = new BinaryFileInformation(); binFileInfo.NewGenFile = outFile; binFileInfo.RelativeFilePath = relativeFilePath; parentNode.AddChildNode(binFileInfo, fileName); } AddFileCountToPreviousEventAndRefire(_ProgressHelper, 1); return fileCount; } ProviderInfo provider; Type iteratorType = _Project.GetIteratorTypeFromProviders(file.IteratorName, out provider); IScriptBaseObject[] iteratorObjects = GetIteratorObjects(iteratorType, provider); if (iteratorObjects != null) { if (iteratorType.IsArray) { throw new NotImplementedException("Array iterator types not handled for static files yet. Please inform [email protected] about this error."); } foreach (IScriptBaseObject iteratorObject in iteratorObjects) { string fileName = UpdateScriptName(iteratorObject, file); string relativeFilePath = Path.Combine(folderName, fileName); string fullPath = Path.Combine(absoluteBasePath, relativeFilePath); if (GetSkipCurrentFile(file, Path.Combine(_Project.ProjectSettings.OutputPath, relativeFilePath))) { // Skip the file. continue; } _FileController.WriteResourceToFile(_Loader.CurrentAssembly, file.StaticFileName, fullPath); _Project.AddGeneratedFile(new GeneratedFile(file.Name, fullPath, relativeFilePath, "", file.IteratorName)); if (addToProjectFileTree) { BinaryFile outFile = new BinaryFile(fullPath, false); BinaryFileInformation binFileInfo = new BinaryFileInformation(); binFileInfo.RelativeFilePath = relativeFilePath; binFileInfo.NewGenFile = outFile; parentNode.AddChildNode(binFileInfo, fileName); } fileCount++; AddFileCountToPreviousEventAndRefire(_ProgressHelper, 1); } } return fileCount; }
/// <summary> /// Creates a new node and adds it as a child. /// </summary> /// <param name="associatedFileInformation">The IFileInformation to associated with the node. Can be null if it needs to be set later.</param> /// <param name="nodeText">The text of the node. Can be null if it needs to be set later.</param> /// <returns>The created node.</returns> public virtual ProjectFileTreeNode AddChildNode(IFileInformation associatedFileInformation, String nodeText) { if (nodeText == null) nodeText = ""; ProjectFileTreeNode node = new ProjectFileTreeNode(this, parentTree); node.Text = nodeText; node.associatedFile = associatedFileInformation; if (childNodes.Any(c => c.Text == nodeText)) { log.ErrorFormat("Duplicated {0} node called {1}", associatedFileInformation == null ? "folder" : "file", nodeText); } childNodes.Add(node); parentTree.AddNode(node); status = ProjectFileStatusEnum.Folder; RaiseNodeChangedEvent(this, true); return node; }
private bool ProcessScriptObject(object scriptObject, string folderName, IScript script, ProjectFileTreeNode parentNode) { bool success = true; string scriptName = UpdateScriptName(scriptObject, script); string fileName = Path.Combine(folderName, scriptName); _Loader.SetGeneratedFileNameOnTemplate(Path.Combine(_Project.ProjectSettings.OutputPath, fileName)); if (scriptName.IndexOf("#") >= 0) { success = false; } if (success) { TextFileInformation fileInfo = new TextFileInformation(); fileInfo.RelativeFilePath = fileName; try { // Reset the SkipCurrentFile and CurrentFileName variable _Loader.CallTemplateFunction(TemplateHelper.ResetSkipCurrentFileFunctionName); _Loader.CallTemplateFunction(TemplateHelper.ResetCurrentFileNameFunctionName); // Call the script file function to get the file text body object[] parameters = new[] { scriptObject }; // Check whether we must skip the current file string templateOutput = (string)_Loader.CallTemplateFunction(script.ScriptName, ref parameters); if (_ProgressHelper.IsCancellationPending()) return false; bool skipCurrentFile = (bool)_Loader.CallTemplateFunction(TemplateHelper.GetSkipCurrentFileFunctionName); if (!skipCurrentFile) { templateOutput = Utility.StandardizeLineBreaks(templateOutput, Utility.LineBreaks.Windows); string codeInsertionFilename = (string)_Loader.CallTemplateFunction(TemplateHelper.GetCurrentFileNameFunctionName); if (string.IsNullOrEmpty(codeInsertionFilename)) { string fullPath = Path.Combine(absoluteBasePath, fileName); _FileController.WriteAllText(fullPath, templateOutput); // The file has successfully been written - add it to the GeneratedFiles _Project.AddGeneratedFile(new GeneratedFile(script.FileName, fullPath, fileName, script.ScriptName, script.IteratorName)); // Set the NewGen text to point to that file. fileInfo.NewGenFile = new TextFile(fullPath, false); string versionNumberString = _Loader.GetAssemblyVersionNumber(); VersionNumber versionNumber; if (VersionNumber.TryParse(versionNumberString, out versionNumber)) { // Get the template language from the template function. string templateLanguageString = _Loader.GetTemplateFunctionLanguage(script.ScriptName); try { fileInfo.TemplateLanguage = SyntaxEditorHelper.LanguageEnumFromName(templateLanguageString); } catch (NotImplementedException) { fileInfo.TemplateLanguage = null; } } if (addToProjectFileTree) { parentNode.AddChildNode(fileInfo, scriptName); } } else { // Code insertions were performed. Need to update a node in the tree. // expand the path if (Path.IsPathRooted(codeInsertionFilename) == false) { codeInsertionFilename = RelativePaths.RelativeToAbsolutePath(absoluteBasePath, codeInsertionFilename); } codeInsertionFilename = _FileController.GetFullPath(codeInsertionFilename); // Get the relative path string relativeCodeInsertionFilename = RelativePaths.GetRelativePath(_Project.ProjectSettings.OutputPath, codeInsertionFilename); // If the file is not under the output path, then reset it to the full path if (relativeCodeInsertionFilename.StartsWith("..")) { relativeCodeInsertionFilename = codeInsertionFilename; // We need to add its folder as a root node of the tree if (!parentNode.IsTreeRoot) parentNode = parentNode.ParentTree; } fileInfo.RelativeFilePath = relativeCodeInsertionFilename; string relPathStart = "." + Path.DirectorySeparatorChar; if (fileInfo.RelativeFilePath.StartsWith(relPathStart)) fileInfo.RelativeFilePath = fileInfo.RelativeFilePath.Substring(2); if (addToProjectFileTree) { ProjectFileTree tree; if (!parentNode.IsTreeRoot) tree = parentNode.ParentTree; else tree = (ProjectFileTree)parentNode; var possibleNode = tree.GetNodeAtPath(codeInsertionFilename); if (possibleNode == null) { // Need to create this node. // Create the node and it's parent folders if need be var node = tree.CreateFileNodeForPath(relativeCodeInsertionFilename); node.AssociatedFile = fileInfo; } else { // Update the NewGen text, don't add it to the generated files list. fileInfo = possibleNode.AssociatedFile as TextFileInformation; if (fileInfo == null) throw new NotSupportedException("Cannot code merge a binary file"); } } else { // Write the file to disk _FileController.WriteAllText(codeInsertionFilename, templateOutput); } fileInfo.NewGenFile = new TextFile(templateOutput); } AddFileCountToPreviousEventAndRefire(_ProgressHelper, 1); } } catch (TemplateFunctionException ex) { success = false; string message = "<span class='error'>" + ex.Message + "</span>"; if (ex.InnerException != null) { message += ":<br/>" + Environment.NewLine + "<b>" + ex.InnerException.Message + "</b>" + Environment.NewLine + GetCleanTemplateFunctionErrorStackTrace(ex) + Environment.NewLine + "Target Site: " + ex.InnerException.TargetSite; } RaiseTemplateFunctionCallErrorEvent(ex); // Do nothing, just skip the file because the error will get reported to the user. if (addToProjectFileTree) { parentNode.AddChildNode(fileInfo, scriptName).GenerationError = new GenerationError(fileName, message); } } catch (Exception ex) { string message = "<span class='error'>" + ex.Message + "</span>"; if (ex.InnerException != null) { message += ":<br/>" + Environment.NewLine + "<b>" + ex.InnerException.Message + "</b>" + Environment.NewLine + GetCleanTemplateFunctionErrorStackTrace(ex) + Environment.NewLine + "Target Site: " + ex.InnerException.TargetSite; } if (addToProjectFileTree) { parentNode.AddChildNode(fileInfo, scriptName).GenerationError = new GenerationError(fileName, message); } // Make sure any other type of exception gets thrown throw; } } return success; }