/// <returns> /// Value of specified attribute that is set on the branch or its /// closest ancestor; null if neither branch nor any of its ancestors /// has this attribute set. /// </returns> static IAttributeInstance GetAttributeWithInheritance( IBranch branch, IAttributeKey attrKey) { if (branch == null) { return(null); } var attr = branch.Attributes.Get(attrKey); if (attr != null) { return(attr); } return(GetAttributeWithInheritance(branch.Parent, attrKey)); }
static void Main(string[] args) { string projectAddress; if (args.Length < 1) { Console.Write("Enter path of \"Stabilizer\" example project: "); projectAddress = Console.ReadLine().Trim(); } else { projectAddress = args[0]; } Console.WriteLine("Opening project \"{0}\"...", projectAddress); using (var project = ProjectManager.Open(projectAddress, AccessMode.ReadWrite)) { Console.WriteLine(); var stopwatch = new Stopwatch(); stopwatch.Start(); // Branches in "Stabilizer" project have attributes coming // from PDMS, including such attributes as "Level" and "Purpose". // // The idea of this FRT generator is to: // - select all CAD branches that have "Level" attribute and // that either have or inherit "Purpose" attribute; // - group them first by "Level", then by "Purpose"; and // - inject them into project's FRT hierarchy. // // The resulting FRT will look something like: // <root> // +- Level A // +- Purpose X // +- branch 1 // +- branch 2 // +- ... // +- branch N // +- Purpose Y // +- ... // +- Level B // +- Purpose X // +- ... // Prepare attribute keys for "Level" and "Purpose". IProjectAttributeSource pdmsAttributeSource = project.AttributeSources.GetAll() .Single(attrSrc => attrSrc.Kind.Equals(ProjectAttributeSourceKinds.Pdms)); IAttributeKey levelKey = pdmsAttributeSource.CreateKey("Level"); IAttributeKey purposeKey = pdmsAttributeSource.CreateKey("Purpose"); // Select all CAD branches of the project. IEnumerable <IBranch> cadRootBranches = project.Branches.GetRoots(BranchKind.Cad); IEnumerable <IBranch> allCadBranches = cadRootBranches.Concat( cadRootBranches.SelectMany(cadRoot => cadRoot.Descendants)); // Scan all CAD branches and retrieve their "Level" and "Purpose". var cadBranchesWithLevelAndPurpose = allCadBranches .Select(cadBranch => new { Level = cadBranch.Attributes.Get(levelKey), Purpose = GetAttributeWithInheritance(cadBranch, purposeKey), SourceCadBranch = cadBranch, }) .Where(branchInfo => branchInfo.Level != null && branchInfo.Purpose != null); // Translate data into sequence of FrtBranchInfo and simplify // IAttributeInstances into simple strings. var frtBranchInfos = cadBranchesWithLevelAndPurpose .Select(branchInfo => new FrtBranchInfo { Level = (string)branchInfo.Level.Value, Purpose = (string)branchInfo.Purpose.Value, SourceCadBranch = branchInfo.SourceCadBranch, }); // Sort branch info so that branches can be created sequentially. // The sequence will look something like: // // Level A | Purpose X | branch 1 // Level A | Purpose X | ... // Level A | Purpose X | branch N1 // Level A | Purpose Y | branch 1 // Level A | Purpose Y | ... // Level A | Purpose Y | branch N2 // Level B | Purpose X | branch 1 // Level B | Purpose X | ... // Level B | Purpose X | branch N3 // ... | ... | ... var orderedFrtBranchInfos = frtBranchInfos .OrderBy(branchInfo => branchInfo.Level) .ThenBy(branchInfo => branchInfo.Purpose) .ThenBy(branchInfo => branchInfo.SourceCadBranch.Name); // Translate branch infos to creation params, to be fed into // Branch.Create(). var branchCreationParams = GenerateBranchCreationParams(orderedFrtBranchInfos); // Fastest way to create many branches is with Branches.Create(). // It has significant optimizations, especially for standalone // projects. Current maximum rate, if creating branches one-by-one, // is 6-10 branches per second. Using Branches.Create() it // is possible to create thousands of branches per second. Console.WriteLine("Injecting FRT branches..."); project.Branches.Create(branchCreationParams); Console.WriteLine(); stopwatch.Stop(); Console.WriteLine("Done in {0}.", stopwatch.Elapsed); } Console.WriteLine("Press Enter to exit..."); Console.ReadLine(); }