public static void CombineParentFile(FileObject.ParentFile parent) { var projectInfo = parent.ProjectInfo; // do not process if any child files were unsuccessful if (!parent.ProcessedChildCadFiles.All(x => x.ExecuteSuccessful)) { Program.Log($"Parent file {parent.ProcessedPath} was not processed because one or more of its children were not processed successfully.", Program.MessageType.Error); return; } #region edit script text // make combine script //string combineScriptPath = projectInfo.InboxPath + "\\" + // parent.ChildCadFilesProcessed.First().InboxSubdirectoryName + "\\Backup\\Scripts\\" + // Path.GetFileNameWithoutExtension(parent.ProcessedPath) + "_combine.scr"; var combineScriptPath = $"{projectInfo.InboxPath}\\{parent.ProcessedChildCadFiles.First().ProcessedSubdirectoryName}" + $"\\Backup\\Scripts\\{parent.Trade.Abbreviation}_{parent.Level.Name}_combine.scr"; // insert all children that exist into template on own layer string combineScriptText; using (StreamReader reader = new StreamReader(ScriptPaths.CombineDwgs)) { combineScriptText = reader.ReadToEnd(); } var layersAndInsertsText = string.Empty; // leave out child files that do not exist foreach (string childPath in parent.ChildPaths.Where(x => File.Exists(x))) { var layerName = Regex.Match(Path.GetFileNameWithoutExtension(childPath), @"\d{6}_(.+)-Lev").Groups[1].Value; if (string.IsNullOrWhiteSpace(layerName)) { Program.Log($"Could not parse subtrade for {childPath}, falling back to basename.", Program.MessageType.Error); layerName = Path.GetFileNameWithoutExtension(childPath); } layersAndInsertsText += $"-LAYER MAKE \"{layerName}\"\n\n"; layersAndInsertsText += $"-insert \"{childPath}\"\n0,0,0\n\n\n\n"; } layersAndInsertsText = layersAndInsertsText.TrimEnd('\n'); combineScriptText = combineScriptText.Replace("%LAYERSANDINSERTS%", layersAndInsertsText); // save to inbox folder combineScriptText = combineScriptText.Replace("%COMBINEDFILEPATH%", "\"" + parent.InboxSaveAsPath + "\""); File.WriteAllText(combineScriptPath, combineScriptText); #endregion if (File.Exists(parent.InboxSaveAsPath)) { File.Delete(parent.InboxSaveAsPath); } Program.Log("Combining files " + string.Join(", ", parent.ChildPaths.Where(x => File.Exists(x)).Select(x => Path.GetFileName(x))) + " into: " + Path.GetFileName(parent.ProcessedPath)); var timeBeforeStart = DateTime.Now; RunACCC(parent.TemplatePath, combineScriptPath, true); if (File.Exists(parent.InboxSaveAsPath) && DateTime.Compare(new FileInfo(parent.InboxSaveAsPath).LastWriteTime, timeBeforeStart) > 0) { // if parent file exists and has been modified recently parent.FileInfo = new FileInfo(parent.InboxSaveAsPath); } else { Program.Log("Parent file could not be created.", Program.MessageType.Error); } // copy to Vdc-Merge File.Copy(parent.InboxSaveAsPath, parent.ProcessedPath, true); if (File.Exists(parent.ProcessedPath) && DateTime.Compare(new FileInfo(parent.ProcessedPath).LastWriteTime, timeBeforeStart) > 0) { // if parent file exists and has been modified recently parent.FileInfo = new FileInfo(parent.ProcessedPath); parent.ExecuteSuccessful = true; } else { Program.Log("Parent file could not be copied to Vdc-Merge folder.", Program.MessageType.Error); } }
static int Update(CLI.UpdateOptions opts) { // get project number if (!Regex.IsMatch(opts.Project, "^\\d{6}$")) { throw new Exception("Invalid project number"); } string projectNumber = opts.Project; logFile = $"{turingSettings.LogFileDirectory}\\{projectNumber}_{DateTime.Now.ToString("yyyy-MM-dd(HHmm)")}.txt"; Log("Project number: " + projectNumber); // check command line switches bool noDl = opts.Nodl; if (noDl) { Log("360 Sync download disabled"); } bool nwd = opts.Nwd; if (!nwd) { Log("NWD creation disabled"); } bool showUnknown = opts.ShowUnknown; bool showIgnored = opts.ShowIgnored; // find turing project config xml file var projectConfigFile = Path.Combine(turingSettings.ProjectConfigFileDirectory, projectNumber + ".xml"); if (!File.Exists(projectConfigFile)) { throw new Exception("Project config file does not exist at: " + projectConfigFile); } var projectDirectory = new DirectoryInfo(turingSettings.ProjectsDirectory).GetDirectories(projectNumber + "*").SingleOrDefault(); if (projectDirectory == null) { throw new Exception("Project path not found"); } // TODO could read from config file string projectPath = projectDirectory.FullName; // get project info Log("Getting project info..."); var projectInfo = new ProjectInfo(projectPath); // find download folder // TODO could read from config file var downloadFolderPath = Path.Combine(turingSettings.RootDownloadDirectory, $"{projectInfo.ProjectNumber} - {projectInfo.ProjectName}"); var downloadFolder = new DirectoryInfo(downloadFolderPath); if (!downloadFolder.Exists) { Log($"Download folder not found. Creating {downloadFolder.FullName}", MessageType.Warning); downloadFolder.Create(); } // get info from config file projectSettings = new ProjectSettings(projectConfigFile); if (noDl == false) { Log("360Sync config file found: " + projectSettings.ConfigName360Sync); if (projectSettings.FileSource == ProjectSettings.FileSourceType.BIM360Glue) { // set hostname Log("Setting hostname: " + projectSettings.Hostname); Set360SyncHostname(projectSettings.Hostname); } // start 360Sync process and wait for it to end Log("Running 360Sync..."); // TODO need to make sure glue source is not disabled Run360Sync(projectSettings.ConfigName360Sync); } // get all files in download folder Log("Checking downloaded files..."); var fileInfos = downloadFolder.GetFiles("*", SearchOption.AllDirectories); // create file objects var fileObjects = CreateFileObjects(fileInfos, projectInfo); // CAD files to process and files to copy var newFiles = fileObjects.Where(x => x.TaskType == TaskType.ProcessCad || x.TaskType == TaskType.Copy).ToList(); // moved to file downloading program //foreach (var newFile in newFiles) { // newFile.SetFileStatus(FileStatus.Downloaded); //} projectInfo.IgnoredFiles = fileObjects.Where(x => x.TaskType == TaskType.Ignore).ToList(); var cadFilesToProcess = newFiles.OfType <FileObject.CadFile>().ToList(); Log($"{cadFilesToProcess.Count()} files to update: " + string.Join(", ", cadFilesToProcess.Select(x => x.FileInfo.Name))); projectInfo.FilesToCopy = newFiles.OfType <FileObject.NonCadFile>().ToList(); Log($"{projectInfo.FilesToCopy.Count()} files to copy over: " + string.Join(", ", projectInfo.FilesToCopy.Select(x => x.FileInfo.Name))); projectInfo.UnknownFiles = fileObjects.Where(x => x.TaskType == TaskType.Unknown).ToList(); if (showUnknown) { Log($"{projectInfo.UnknownFiles.Count} files not recognized: " + string.Join(", ", projectInfo.UnknownFiles.Select(x => x.FileInfo.Name))); } if (showIgnored) { Log($"{projectInfo.IgnoredFiles.Count} files ignored: " + string.Join(", ", projectInfo.IgnoredFiles.Select(x => x.FileInfo.Name))); } if (newFiles.Count == 0) { Log("No new files found. Ending process"); return(0); } projectInfo.ProcessedFiles = new List <ICadFile>(); projectInfo.FailedFiles = new List <IFileObject>(); // execute tasks if (cadFilesToProcess.Count + projectInfo.FilesToCopy.Count == 0) { Log("No actions to take. Ending process"); return(0); } else { if (cadFilesToProcess.Count > 0) { #region process cad files Log("Preparing files"); foreach (var cadFileToProcess in cadFilesToProcess) { cadFileToProcess.SetFileStatus(FileStatus.Processing); cadFileToProcess.PrepareForProcessing(); } var preparedFiles = cadFilesToProcess.Where(x => x.PrepareSuccessful).ToList(); AutoCad.Updating.AssignInboxFolders(preparedFiles); var parallelOptions = new ParallelOptions() { MaxDegreeOfParallelism = 10 }; Log("Processing files."); //// for debug //// process cad files in serial //foreach (var preparedFile in preparedFiles) { // preparedFile.ExecuteTask(); //} // process cad files Parallel.ForEach(preparedFiles, parallelOptions, (preparedFile) => { preparedFile.ExecuteTask(); }); var processedCadFiles = preparedFiles.Where(x => x.ExecuteSuccessful); // check if cads successful foreach (var cadFileToProcess in cadFilesToProcess) { if (cadFileToProcess.ExecuteSuccessful) { projectInfo.ProcessedFiles.Add(cadFileToProcess); cadFileToProcess.SetFileStatus(FileStatus.Ready); } else { projectInfo.FailedFiles.Add(cadFileToProcess); cadFileToProcess.SetFileStatus(FileStatus.Failed); } } var childFiles = processedCadFiles.Where(x => x.IsChild).ToArray(); if (childFiles.Length > 0) { // create parent file objects Log("Creating parent files."); var parents = new List <FileObject.ParentFile>(); var childFilesWithDistinctParent = childFiles.DistinctBy(x => x.ParentPath).ToArray(); foreach (var childFile in childFilesWithDistinctParent) { var parent = new FileObject.ParentFile() { ProcessedBaseName = Path.GetFileNameWithoutExtension(childFile.ParentPath), InboxSaveAsPath = $"{childFile.ProjectInfo.InboxPath}\\{childFile.ProcessedSubdirectoryName}\\{Path.GetFileNameWithoutExtension(childFile.ParentPath)}.dwg", ProcessedPath = childFile.ParentPath, Level = childFile.Level, Trade = childFile.Trade, ProjectInfo = childFile.ProjectInfo, TemplatePath = childFile.TemplatePath }; parents.Add(parent); } foreach (var parent in parents) { parent.SetFileStatus(FileStatus.Processing); var parentProcessedDir = Path.GetDirectoryName(parent.ProcessedPath); // get all parent's children from database Files_IO var childData = Database.Read( "select FILE_INTERNAL_NAME " + "from AIS_DEV.VDC_FILES " + $"where FILE_PROJECT_NUMBER = {projectSettings.ProjectNumber} " + $"and FILE_PARENT_NAME like '{Path.GetFileNameWithoutExtension(parent.ProcessedPath)}'"); if (childData.Length == 0) { Log($"No child files found for: {parent.ProcessedBaseName}", MessageType.Error); continue; } OracleString[] allChildrenBaseNames = childData.Select(x => (OracleString)x.Single()).ToArray(); // child path are in same directory as parent in vdc-merge directory parent.ChildPaths = allChildrenBaseNames.Select(x => Path.Combine(parentProcessedDir, x.Value + ".dwg")).ToList(); parent.ProcessedChildCadFiles = processedCadFiles.Where(x => x.ParentPath == parent.ProcessedPath); } //// debug process parent files //foreach (var parent in parents) { // AutoCad.Updating.CombineParentFile(parent); //} // process parent files Parallel.ForEach(parents, parallelOptions, parent => { AutoCad.Updating.CombineParentFile(parent); }); // check if parents successful foreach (var parent in parents) { if (parent.ExecuteSuccessful) { projectInfo.ProcessedFiles.Add(parent); //SetFileStatus(parent, FileStatus.Ready); parent.SetFileStatus(FileStatus.Ready); } else { projectInfo.FailedFiles.Add(parent); //SetFileStatus(parent, FileStatus.Failed); parent.SetFileStatus(FileStatus.Failed); } } } // TODO this should happen during file processing // if update successful, change Last Processed time of file in database if (projectInfo.ProcessedFiles.Count > 0) { Log("Updating database timestamps"); foreach (var dwg in projectInfo.ProcessedFiles) { UpdateLastProcessedTimestamp(dwg.ProcessedPath, projectNumber, useExternalFileName: false); } } if (nwd) { // create nwd for quality checking Log("Creating NWDs"); Parallel.ForEach(projectInfo.ProcessedFiles.Select(x => x.ProcessedPath), file => { NwdCreator.Create(file, file.Replace(".dwg", ".nwd")); File.Delete(file.Replace(".dwg", ".nwc")); }); } #endregion } if (projectInfo.FilesToCopy.Count > 0) { #region copy noncad files Log("Copying over files"); foreach (var fileObject in projectInfo.FilesToCopy) { var destDir = Path.Combine(fileObject.ProjectInfo.VdcMergePath, "MISC"); fileObject.DestinationPath = Path.Combine(destDir, fileObject.FileInfo.Name); Directory.CreateDirectory(destDir); // get last write time of existing file DateTime existingLastWriteTime; if (File.Exists(fileObject.DestinationPath)) { existingLastWriteTime = File.GetLastWriteTime(fileObject.FileInfo.FullName); } else { existingLastWriteTime = DateTime.MinValue; } // copy file to vdc-merge misc folder and overwrite try { File.Copy(fileObject.FileInfo.FullName, fileObject.DestinationPath, true); } catch (IOException) { Log($"Could not copy over file {fileObject.FileInfo.Name}", MessageType.Error); } // doesnt update if copying same file, uses same lastWrite timestamp var newLastWriteTime = File.GetLastWriteTime(fileObject.FileInfo.FullName); // check if copy successful if (File.Exists(fileObject.DestinationPath) && DateTime.Compare(existingLastWriteTime, newLastWriteTime) <= 0) { fileObject.CopySuccessful = true; //SetFileStatus(fileObject, FileStatus.Ready); fileObject.SetFileStatus(FileStatus.Ready); } else { projectInfo.FailedFiles.Add(fileObject); //SetFileStatus(fileObject, FileStatus.Failed); fileObject.SetFileStatus(FileStatus.Failed); } } // update database timestamps var successfullyCopiedFiles = projectInfo.FilesToCopy.Where(x => x.CopySuccessful).ToArray(); if (successfullyCopiedFiles.Length > 0) { Log("Updating copied files timestamps"); foreach (var copiedFile in successfullyCopiedFiles) { UpdateLastProcessedTimestamp(copiedFile.DestinationPath, projectNumber, useExternalFileName: true); } } #endregion } // create trade file update email var attachments = new string[] { }; var coordEmailfileName = projectNumber + "_" + DateTime.Now.ToString("yyyy-MM-dd(HHmm)") + ".msg"; var coordEmailFilePath = turingSettings.CoordEmailDirectory + "\\" + coordEmailfileName; projectInfo.ProcessedFiles = projectInfo.ProcessedFiles.OrderBy(x => x.FileInfo.Name).ToList(); projectInfo.FailedFiles = projectInfo.FailedFiles.OrderBy(x => x.FileInfo.Name).ToList(); if (projectInfo.ProcessedFiles.Count() > 0) { Log("Creating coordination email..."); Notification.SaveCoordEmailOutlook(projectInfo, coordEmailFilePath, attachments); } Log("Sending notification to VDC..."); Notification.SendTuringNotification(projectInfo, downloadFolder, coordEmailFilePath); } Log("Process complete!"); return(0); }