/// <summary> /// Adds Sheets data to collection if such exists, otherwise creates a new one. /// </summary> public static void ProcessSheets(ActionType action, Document doc, string centralPath) { var project = MissionControlSetup.Projects[centralPath]; switch (action) { case ActionType.CheckIn: if (!ServerUtilities.GetByCentralPath(centralPath, "sheets/centralpath", out SheetData sData)) { if (ServerUtilities.Post(new SheetData { CentralPath = centralPath.ToLower() }, "sheets", out sData)) { ServerUtilities.Put(new { id = sData.Id }, "projects/" + project.Id + "/addsheet"); if (MissionControlSetup.SheetsData.ContainsKey(centralPath)) { MissionControlSetup.SheetsData.Remove(centralPath); } MissionControlSetup.SheetsData.Add(centralPath, sData); // store sheets record } } if (sData != null) { if (MissionControlSetup.SheetsData.ContainsKey(centralPath)) { MissionControlSetup.SheetsData.Remove(centralPath); } MissionControlSetup.SheetsData.Add(centralPath, sData); // store sheets record Messenger.Default.Send(new CommunicatorDataDownloaded { CentralPath = centralPath, Type = DataType.Sheets }); new Thread(() => new SheetTracker.SheetTracker().SynchSheets(doc)) { Priority = ThreadPriority.BelowNormal, IsBackground = true }.Start(); } break; case ActionType.Synch: if (MissionControlSetup.SheetsData.ContainsKey(centralPath)) { new Thread(() => new SheetTracker.SheetTracker().SynchSheets(doc)) { Priority = ThreadPriority.BelowNormal, IsBackground = true }.Start(); } break; default: throw new ArgumentOutOfRangeException(nameof(action), action, null); } }
/// <summary> /// Adds Links data to collection if such exists, otherwise creates a new one. /// </summary> private static void ProcessLinks(Document doc, string centralPath) { var project = MissionControlSetup.Projects[centralPath]; var data = new DataRangeRequest(centralPath.ToLower()); if (!ServerUtilities.Post(data, "links/linkstats", out LinkData lData)) { if (ServerUtilities.Post(new LinkData { CentralPath = centralPath.ToLower() }, "links", out lData)) { ServerUtilities.Put(new { id = lData.Id }, "projects/" + project.Id + "/addlink"); if (MissionControlSetup.LinksData.ContainsKey(centralPath)) { MissionControlSetup.LinksData.Remove(centralPath); } MissionControlSetup.LinksData.Add(centralPath, lData); // store links record } } if (lData != null) { if (MissionControlSetup.LinksData.ContainsKey(centralPath)) { MissionControlSetup.LinksData.Remove(centralPath); } MissionControlSetup.LinksData.Add(centralPath, lData); // store links record Messenger.Default.Send(new HealthReportSummaryAdded { Data = lData, Type = SummaryType.Links }); new Thread(() => new LinkMonitor().PublishData(doc, lData.Id)) { Priority = ThreadPriority.BelowNormal, IsBackground = true }.Start(); } }
/// <summary> /// Checks if Families collection exists and creates one if it doesn't. Since families /// stats are published on demand by another tool there is no need to publish them here. /// </summary> private static void ProcessFamilies(string centralPath) { var project = MissionControlSetup.Projects[centralPath]; // (Konrad) For families we only need to make sure that we have the collection id. It will be used // by the Tasks. The actual data gets posted by FamilyPublish Tool. if (!ServerUtilities.GetByCentralPath(centralPath, "families/centralpath", out FamilyData fData)) { if (ServerUtilities.Post(new FamilyData { CentralPath = centralPath.ToLower() }, "families", out fData)) { ServerUtilities.Put(new { id = fData.Id }, "projects/" + project.Id + "/addfamilies"); if (MissionControlSetup.FamilyData.ContainsKey(centralPath)) { MissionControlSetup.FamilyData.Remove(centralPath); } MissionControlSetup.FamilyData.Add(centralPath, fData); // store families record } } else { if (MissionControlSetup.FamilyData.ContainsKey(centralPath)) { MissionControlSetup.FamilyData.Remove(centralPath); } MissionControlSetup.FamilyData.Add(centralPath, fData); // store families record Messenger.Default.Send(new HealthReportSummaryAdded { Data = fData, Type = SummaryType.Families }); Messenger.Default.Send(new CommunicatorDataDownloaded { CentralPath = centralPath, Type = DataType.Families }); } }
/// <summary> /// Publishes information about linked models/images/object styles in the model. /// </summary> public void PublishData() { try { if (!MonitorUtilities.IsUpdaterOn(Project, Config, UpdaterGuid)) { return; } if (string.IsNullOrEmpty(FamiliesId)) { return; } var unusedFamilies = 0; var oversizedFamilies = 0; var inPlaceFamilies = 0; var families = new FilteredElementCollector(Doc) .OfClass(typeof(Family)) .Cast <Family>() .ToList(); var config = MissionControlSetup.Configurations.ContainsKey(CentralPath) ? MissionControlSetup.Configurations[CentralPath] : null; var familyNameCheck = new List <string> { "HOK_I", "HOK_M" }; //defaults if (config != null) { familyNameCheck = config.Updaters.First(x => string.Equals(x.UpdaterId, Properties.Resources.HealthReportTrackerGuid, StringComparison.OrdinalIgnoreCase)).UserOverrides.FamilyNameCheck.Values; } //var count = 0; var famOutput = new List <FamilyItem>(); StatusBarManager.InitializeProgress("Exporting Family Info:", families.Count); foreach (var family in families) { // (Konrad) Uncomment for Debug. //count++; //if (count > 5) continue; if (StatusBarManager.Cancel) { StatusBarManager.CancelProgress(); return; } StatusBarManager.StepForward(); var sizeCheck = false; var instanceCheck = false; var nameCheck = false; var instances = CountFamilyInstances(family); if (instances == 0) { unusedFamilies++; instanceCheck = true; } if (family.IsInPlace) { inPlaceFamilies++; } long size = 0; var refPlanes = 0; var arrays = 0; var voids = 0; var nestedFamilies = 0; var parameters = 0; var sizeStr = "0Kb"; var images = 0; try { var famDoc = Doc.EditFamily(family); var storedPath = famDoc.PathName; if (File.Exists(storedPath)) { size = new FileInfo(storedPath).Length; } else { if (string.IsNullOrWhiteSpace(famDoc.Title)) { continue; // could cause an exception } var myDocPath = IsCitrixMachine(Environment.MachineName) ? "B:\\Temp" : Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); var path = myDocPath + "\\temp_" + famDoc.Title; if (path.IndexOfAny(Path.GetInvalidPathChars()) != -1) { continue; // could cause an exception } if (File.Exists(path)) { TryToDelete(path); } famDoc.SaveAs(path); size = new FileInfo(path).Length; TryToDelete(path); } refPlanes = new FilteredElementCollector(famDoc) .OfClass(typeof(ReferencePlane)) .GetElementCount(); var filter = new LogicalOrFilter(new List <ElementFilter> { new ElementClassFilter(typeof(LinearArray)), new ElementClassFilter(typeof(RadialArray)) }); arrays = new FilteredElementCollector(famDoc) .WherePasses(filter) .GetElementCount(); images = new FilteredElementCollector(famDoc) .OfClass(typeof(ImageType)) .WhereElementIsElementType() .GetElementCount(); voids = new FilteredElementCollector(famDoc) .OfClass(typeof(Extrusion)) .Cast <Extrusion>() .Count(x => !x.IsSolid); nestedFamilies = new FilteredElementCollector(famDoc) .OfClass(typeof(Family)) .GetElementCount(); #if RELEASE2015 //(Konrad) Since Revit 2015 API doesn't support this we will just skip it. parameters = 0; #else parameters = new FilteredElementCollector(famDoc) .OfClass(typeof(ParameterElement)) .GetElementCount(); #endif famDoc.Close(false); sizeStr = StringUtilities.BytesToString(size); if (size > 1000000) { oversizedFamilies++; // >1MB sizeCheck = true; } } catch (Exception ex) { Log.AppendLog(LogMessageType.EXCEPTION, ex.Message); Log.AppendLog(LogMessageType.ERROR, "Failed to retrieve size, refPlanes, arrays, voids..."); } if (!familyNameCheck.Any(family.Name.Contains)) { nameCheck = true; } var famItem = new FamilyItem { Name = family.Name, ElementId = family.Id.IntegerValue, Size = sizeStr, SizeValue = size, Instances = instances, ArrayCount = arrays, RefPlaneCount = refPlanes, VoidCount = voids, NestedFamilyCount = nestedFamilies, ParametersCount = parameters, ImageCount = images, Tasks = new List <FamilyTask>() }; if (nameCheck || sizeCheck || instanceCheck) { famItem.IsFailingChecks = true; } else { famItem.IsFailingChecks = false; } famOutput.Add(famItem); } if (!ServerUtilities.GetByCentralPath(CentralPath, "families/centralpath", out FamilyData famStat)) { Log.AppendLog(LogMessageType.ERROR, "Failed to retrieve Families data."); return; } var famDict = new Dictionary <string, FamilyItem>(); if (famStat != null) { famDict = famStat.Families.ToDictionary(x => x.Name, x => x); } // (Konrad) I know it's not efficient to iterate this list yet again, but // I want to minimize the amount of time between publishing families and // retrieving them from database to avoid someone addind tasks to DB while // we are exporting and hence losing them after the export. foreach (var family in famOutput) { if (famDict.ContainsKey(family.Name)) { family.Tasks.AddRange(famDict[family.Name].Tasks); famDict.Remove(family.Name); } } foreach (var item in famDict.Values.ToList()) { item.IsDeleted = true; famOutput.Add(item); } var familyStats = new FamilyData { CentralPath = CentralPath.ToLower(), TotalFamilies = famOutput.Count, UnusedFamilies = unusedFamilies, InPlaceFamilies = inPlaceFamilies, OversizedFamilies = oversizedFamilies, CreatedBy = Environment.UserName.ToLower(), CreatedOn = DateTime.UtcNow, Families = famOutput }; if (!ServerUtilities.Put(familyStats, "families/" + famStat.Id)) { Log.AppendLog(LogMessageType.ERROR, "Failed to publish Families data."); } StatusBarManager.FinalizeProgress(); } catch (Exception ex) { Log.AppendLog(LogMessageType.EXCEPTION, ex.Message); } }