private static void printOneRelationship(Guid id, DateTimeOffset createdOn, bool isReadOnly, bool isService, bool isDeleted, string domain, string type, string entId, string withDomain, string withType, string withEntId) { ColourConsole.WriteInfo($"One Relationship Data"); ColourConsole.WriteInfo($" Relationship Id: {id}"); ColourConsole.WriteInfo($" CreatedOn: {createdOn}"); ColourConsole.WriteInfo($" isReadOnly: {isReadOnly}"); ColourConsole.WriteInfo($" isService: {isService}"); ColourConsole.WriteInfo($" isDeleted: {isDeleted}"); ColourConsole.WriteInfo($" entities: "); ColourConsole.WriteInfo($" one entitity: domain={domain}\n" + $" type={type}\n" + $" id={entId}\n"); ColourConsole.WriteInfo($" another entitity: domain={withDomain}\n" + $" type={withType}\n" + $" id={withEntId}"); }
private static async Task RunAsync() { var configuration = new SampleConfiguration(); //----------------------------------------------------------------------------------------------------- // Sample Configuration //----------------------------------------------------------------------------------------------------- // Either add a .adsk-forge/SampleConfiguration.json file to the Environment.SpecialFolder.UserProfile // folder (this will be different on windows vs mac/linux) or pass the optional configuration // Dictionary<string, string> to set AuthToken, Account and Project values on SampleConfiguration // // configuration.Load(new Dictionary<string, string> // { // { "AuthToken", "Your Forge App OAuth token" }, // { "AccountId", "Your BIM 360 account GUID (no b. prefix)" }, // { "ProjectId", "Your BIM 360 project GUID (no b. prefix)"} // }); // // See: SampleConfigurationExtensions.cs for more information. //----------------------------------------------------------------------------------------------------- configuration.Load(); // create a service provider for IoC composition var serviceProvider = new ServiceCollection() .AddSampleForgeServices(configuration) .BuildServiceProvider(); // load the state from CreateModelSetSample var fileManager = serviceProvider.GetRequiredService <ILocalFileManager>(); var modelSetCreateSampleState = await fileManager.ReadJsonAsync <CreateModelSetSampleState>(); ColourConsole.WriteSuccess($"Loaded sample state"); // make sure this model set exists var modelSetClient = serviceProvider.GetRequiredService <IModelSetClient>(); var modelSet = await modelSetClient.GetModelSetAsync(modelSetCreateSampleState.ModelSet.ContainerId, modelSetCreateSampleState.ModelSet.ModelSetId) ?? throw new InvalidOperationException($"Could not find model set {modelSetCreateSampleState.ModelSet.ModelSetId}, have you run CreateModelSetSample?"); ColourConsole.WriteSuccess($"Found model set {modelSet.ModelSetId}"); // See if we can find any model set versions, remember there is a time dalay between documents being extracted // by BIM 360 Docs and the model coordination system's processing of these extracted documents. If you have jumped // immediatly to this sample having run CreateModelSetSample it could be that you are working faster than Docs :-) var modelSetVersions = await modelSetClient.GetModelSetVersionsAsync(modelSetCreateSampleState.ModelSet.ContainerId, modelSetCreateSampleState.ModelSet.ModelSetId, null, null); if (modelSetVersions.ModelSetVersions.Count > 0) { foreach (var version in modelSetVersions.ModelSetVersions.OrderBy(v => v.Version)) { ColourConsole.WriteSuccess($"Found model set version {version.Version:00} : {version.CreateTime:u}, {version.Status}"); } } else { ColourConsole.WriteInfo($"No model set verisons found for {modelSetCreateSampleState.ModelSet.ModelSetId}, try again later."); } // If we found model set versions, demonstrate loading a model set by verison number if (modelSetVersions?.ModelSetVersions.Count > 0) { ColourConsole.WriteInfo("Demonstrate loading model set version by number"); var version = await modelSetClient.GetModelSetVersionAsync(modelSetCreateSampleState.ModelSet.ContainerId, modelSetCreateSampleState.ModelSet.ModelSetId, 1); ColourConsole.WriteSuccess($"First model set version {version.Version:00} : {version.CreateTime:u)}, {version.Status}"); } if (modelSetVersions?.ModelSetVersions.Count > 0) { ColourConsole.WriteInfo("Demonstrate loading latest model set version"); var latest = await modelSetClient.GetModelSetVersionLatestAsync(modelSetCreateSampleState.ModelSet.ContainerId, modelSetCreateSampleState.ModelSet.ModelSetId); ColourConsole.WriteSuccess($"Latest model set version {latest.Version:00} : {latest.CreateTime:u}, {latest.Status}"); } }
private static async Task RunAsync() { var configuration = new SampleConfiguration(); //----------------------------------------------------------------------------------------------------- // Sample Configuration //----------------------------------------------------------------------------------------------------- // Either add a .adsk-forge/SampleConfiguration.json file to the Environment.SpecialFolder.UserProfile // folder (this will be different on windows vs mac/linux) or pass the optional configuration // Dictionary<string, string> to set AuthToken, Account and Project values on SampleConfiguration // // configuration.Load(new Dictionary<string, string> // { // { "AuthToken", "Your Forge App OAuth token" }, // { "AccountId", "Your BIM 360 account GUID (no b. prefix)" }, // { "ProjectId", "Your BIM 360 project GUID (no b. prefix)"} // }); // // See: SampleConfigurationExtensions.cs for more information. //----------------------------------------------------------------------------------------------------- configuration.Load(); // create a service provider for IoC composition var serviceProvider = new ServiceCollection() .AddSampleForgeServices(configuration) .BuildServiceProvider(); // load the state from GetClashResultsSample this includes the latest // model set version that was associated with the clash test. It means // the results of this query relate to the clashing objects in the // proceeding sample, GetClashresultsSample var fileManager = serviceProvider.GetRequiredService <ILocalFileManager>(); var clashResultSampleState = await fileManager.ReadJsonAsync <GetClashResultsSampleState>() ?? throw new InvalidOperationException("Could not load GetClashResultsSampleState.json, have you run GetClashResultsSample?"); // load the model set verison from the GetClashresultsSample var modelSetClient = serviceProvider.GetRequiredService <IModelSetClient>(); var modelSetVersion = await modelSetClient.GetModelSetVersionAsync( clashResultSampleState.Container, clashResultSampleState.Latest.ModelSetId, clashResultSampleState.Latest.ModelSetVersion) ?? throw new InvalidOperationException($"Error could not load latest model set version for model set {clashResultSampleState.Latest.ModelSetId}, have you run GetClashResultsSample?"); // next load the index manifest for the model set verison // this object contains the look-up values for the seed files // documents and databases which were used to build the index. You // will need these valuse to display query results in the LMV if // they are viewable in 3D var modelSetIndex = serviceProvider.GetRequiredService <IModelSetIndex>(); var indexManifest = await modelSetIndex.GetManifest( clashResultSampleState.Container, clashResultSampleState.Latest.ModelSetId, clashResultSampleState.Latest.ModelSetVersion) ?? throw new InvalidOperationException($"No indfex manifest found for {clashResultSampleState.Latest.ModelSetVersion}:{clashResultSampleState.Latest.ModelSetVersion}"); ColourConsole.WriteSuccess($"Manifest contains {indexManifest.SeedFiles.Count} seed files."); // load the fields for the index and go after the field with a name == "name" and category == "__name__" var fields = await modelSetIndex.GetFields(clashResultSampleState.Container, clashResultSampleState.Latest.ModelSetId, clashResultSampleState.Latest.ModelSetVersion); ColourConsole.WriteSuccess($"Loaded {fields.Count} unique index fields"); var nameField = fields.Values.SingleOrDefault( f => f.Name.Equals("name", StringComparison.OrdinalIgnoreCase) && f.Category.Equals("__name__", StringComparison.OrdinalIgnoreCase)); // run a query to find all the objects which have a name as defined by (name == "name" && category == "__name__") // the not missing S3 select keywords assert that this projection is in the data string query = $"select s.file, s.db, s.docs, s.id, s.{nameField.Key} from s3object s where s.{nameField.Key} is not missing"; ColourConsole.WriteInfo(query); var queryResults = await modelSetIndex.Query( clashResultSampleState.Container, clashResultSampleState.Latest.ModelSetId, clashResultSampleState.Latest.ModelSetVersion, query); ColourConsole.WriteSuccess($"Query results downloaded to {queryResults.FullName}"); // itterate over the results and count the number of rows returned // substituteFieldkeys == true below will pull out the unique set of // fields in this data var reader = new IndexResultReader(queryResults, fields); var summary = await reader.ReadToEndAsync(null, true); ColourConsole.WriteSuccess($"Query returned {summary.RowCount} objects with {summary.Fields.Count} unique fields."); }
public static async Task RunAsync() { var configuration = new SampleConfiguration(); //----------------------------------------------------------------------------------------------------- // Sample Configuration //----------------------------------------------------------------------------------------------------- // Either add a .adsk-forge/SampleConfiguration.json file to the Environment.SpecialFolder.UserProfile // folder (this will be different on windows vs mac/linux) or pass the optional configuration // Dictionary<string, string> to set AuthToken, Account and Project values on SampleConfiguration // // configuration.Configure(new Dictionary<string, string> // { // { "AuthToken", "Your Forge App OAuth token" }, // { "AccountId", "Your BIM 360 account GUID (no b. prefix)" }, // { "ProjectId", "Your BIM 360 project GUID (no b. prefix)"} // }); // // See: SampleConfigurationExtensions.cs for more information. //----------------------------------------------------------------------------------------------------- configuration.Load(); // create a service provider for IoC composition var serviceProvider = new ServiceCollection() .AddSampleForgeServices(configuration) .BuildServiceProvider(); // load the state from GetClashResultsSample var fileManager = serviceProvider.GetRequiredService <ILocalFileManager>(); // get the issue container for this project var dataClient = serviceProvider.GetRequiredService <IForgeDataClient>(); //Verifying project id and name dynamic obj = await dataClient.GetProjectAsJObject() ?? throw new InvalidOperationException($"Could not load prject {configuration.ProjectId}"); string project_id = obj.data.id; string project_name = obj.data.attributes.name; ColourConsole.WriteSuccess($"Verifying project id and name {project_id}, {project_name}"); //initialize relationship client var relationshipClient = serviceProvider.GetRequiredService <IRelationshipClient>(); Guid project_id_without_b = new Guid(project_id.Replace("b.", "")); //search all relationships var res_search_without_arg = await relationshipClient.SearchRelationshipsAsync(project_id_without_b, null, null, null, null, null, null, null, null, null, null, null); ColourConsole.WriteSuccess($"Search relationships without arguments: count: {res_search_without_arg.Relationships.Count}"); if (res_search_without_arg.Relationships.Count > 0) { //dump one relationship data ColourConsole.WriteInfo($"One Relationship"); var oneRelationship = res_search_without_arg.Relationships[0]; printOneRelationship(oneRelationship.Id, oneRelationship.CreatedOn, oneRelationship.IsReadOnly, oneRelationship.IsService, oneRelationship.IsDeleted, oneRelationship.Entities[0].Domain, oneRelationship.Entities[0].Type, oneRelationship.Entities[0].Id, oneRelationship.Entities[1].Domain, oneRelationship.Entities[1].Type, oneRelationship.Entities[1].Id); } //search relationships by createAfter and createdBefore var res_search_with_date = await relationshipClient.SearchRelationshipsAsync(project_id_without_b, null, null, null, new DateTime(2020, 7, 15), new DateTime(2020, 7, 20), null, null, null, null, null, null); ColourConsole.WriteSuccess($"Search relationships with Date arguments: count: {res_search_with_date.Relationships.Count}"); if (res_search_with_date.Relationships.Count > 0) { //dump one relationship data ColourConsole.WriteInfo($"One Relationship"); var oneRelationship = res_search_with_date.Relationships[0]; printOneRelationship(oneRelationship.Id, oneRelationship.CreatedOn, oneRelationship.IsReadOnly, oneRelationship.IsService, oneRelationship.IsDeleted, oneRelationship.Entities[0].Domain, oneRelationship.Entities[0].Type, oneRelationship.Entities[0].Id, oneRelationship.Entities[1].Domain, oneRelationship.Entities[1].Type, oneRelationship.Entities[1].Id); } //search relationships by createAfter and createdBefore and continuationToken string one_continuationToken = res_search_without_arg.Page.ContinuationToken; var res_search_with_date_continuetoken = await relationshipClient.SearchRelationshipsAsync(project_id_without_b, null, null, null, new DateTime(2020, 7, 15), new DateTime(2020, 7, 20), null, null, null, null, null, one_continuationToken); ColourConsole.WriteSuccess($"Search relationships with ContinuationToken: count: {res_search_with_date_continuetoken.Relationships.Count}"); if (res_search_with_date_continuetoken.Relationships.Count > 0) { //dump one relationship data ColourConsole.WriteInfo($"One Relationship"); var oneRelationship = res_search_with_date_continuetoken.Relationships[0]; printOneRelationship(oneRelationship.Id, oneRelationship.CreatedOn, oneRelationship.IsReadOnly, oneRelationship.IsService, oneRelationship.IsDeleted, oneRelationship.Entities[0].Domain, oneRelationship.Entities[0].Type, oneRelationship.Entities[0].Id, oneRelationship.Entities[1].Domain, oneRelationship.Entities[1].Type, oneRelationship.Entities[1].Id); } //sync string oneSyncToken = res_search_without_arg.Page.SyncToken; RelationshipSyncRequest rsBody = new RelationshipSyncRequest(); rsBody.SyncToken = oneSyncToken; rsBody.Filters = null; var res_sync = await relationshipClient.RelationshipsSyncAsync(project_id_without_b, rsBody); ColourConsole.WriteSuccess($"Sync relationships with SyncToken:"); ColourConsole.WriteInfo($"Current.Data Count: {res_sync.Current.Data.Count}"); ColourConsole.WriteInfo($"Deleted.Data Count: {res_sync.Deleted.Data.Count}"); ColourConsole.WriteInfo($"moreData : {res_sync.MoreData}"); ColourConsole.WriteInfo($"overwrite : {res_sync.Overwrite}"); if (res_sync.Current.Data.Count > 0) { //dump one relationship data ColourConsole.WriteInfo($"One Current.Data: "); var oneRelationship = res_sync.Current.Data[0]; printOneRelationship(oneRelationship.Id, oneRelationship.CreatedOn, oneRelationship.IsReadOnly, oneRelationship.IsService, oneRelationship.IsDeleted, oneRelationship.Entities[0].Domain, oneRelationship.Entities[0].Type, oneRelationship.Entities[0].Id, oneRelationship.Entities[1].Domain, oneRelationship.Entities[1].Type, oneRelationship.Entities[1].Id); } if (res_sync.Deleted.Data.Count > 0) { //dump one relationship data ColourConsole.WriteInfo($"One Deleted.Data: "); var oneRelationship = res_sync.Deleted.Data[0]; printOneRelationship(oneRelationship.Id, oneRelationship.CreatedOn, oneRelationship.IsReadOnly, oneRelationship.IsService, oneRelationship.IsDeleted, oneRelationship.Entities[0].Domain, oneRelationship.Entities[0].Type, oneRelationship.Entities[0].Id, oneRelationship.Entities[1].Domain, oneRelationship.Entities[1].Type, oneRelationship.Entities[1].Id); } //search relationships with one domain .e.g. modelcoordination var res_search_with_domain = await relationshipClient.SearchRelationshipsAsync(project_id_without_b, "autodesk-bim360-modelcoordination", null, null, new DateTime(2020, 7, 15), new DateTime(2020, 7, 20), null, null, null, null, null, one_continuationToken); ColourConsole.WriteSuccess($"Search relationships with one domain(e.g. modelcoordination) count: {res_search_with_domain.Relationships.Count}"); if (res_search_with_domain.Relationships.Count > 0) { //dump one relationship data ColourConsole.WriteInfo($"One Relationship"); var oneRelationship = res_search_with_domain.Relationships[0]; printOneRelationship(oneRelationship.Id, oneRelationship.CreatedOn, oneRelationship.IsReadOnly, oneRelationship.IsService, oneRelationship.IsDeleted, oneRelationship.Entities[0].Domain, oneRelationship.Entities[0].Type, oneRelationship.Entities[0].Id, oneRelationship.Entities[1].Domain, oneRelationship.Entities[1].Type, oneRelationship.Entities[1].Id); } //search relationships with one domain and type .e.g. modelcoordination and clashgroup var res_search_with_domain_type = await relationshipClient.SearchRelationshipsAsync(project_id_without_b, "autodesk-bim360-modelcoordination", "clashgroup", null, new DateTime(2020, 7, 15), new DateTime(2020, 7, 20), null, null, null, null, null, one_continuationToken); ColourConsole.WriteSuccess($"Search relationships with one domain and type (e.g. modelcoordination & clashgroup). count: {res_search_with_domain_type.Relationships.Count}"); if (res_search_with_domain_type.Relationships.Count > 0) { //dump one relationship data ColourConsole.WriteInfo($"One Relationship"); var oneRelationship = res_search_with_domain_type.Relationships[0]; printOneRelationship(oneRelationship.Id, oneRelationship.CreatedOn, oneRelationship.IsReadOnly, oneRelationship.IsService, oneRelationship.IsDeleted, oneRelationship.Entities[0].Domain, oneRelationship.Entities[0].Type, oneRelationship.Entities[0].Id, oneRelationship.Entities[1].Domain, oneRelationship.Entities[1].Type, oneRelationship.Entities[1].Id); } //search relationships with one domain and type , and withDomain and withType //e.g. modelcoordination & clashgroup - autodesk-bim360-documentmanagement & documentversion // var res_search_with_withDomain_type = await relationshipClient.SearchRelationshipsAsync(project_id_without_b, "autodesk-bim360-modelcoordination", "clashgroup", null, new DateTime(2020, 7, 15), new DateTime(2020, 7, 20), "autodesk-bim360-documentmanagement", "documentversion", null, null, null, one_continuationToken); ColourConsole.WriteSuccess($"Search relationships with one domain and type and withDomain and withType" + $" (e.g. modelcoordination & clashgroup - autodesk-bim360-documentmanagement & documentversion). count: {res_search_with_domain_type.Relationships.Count}"); if (res_search_with_withDomain_type.Relationships.Count > 0) { //dump one relationship data ColourConsole.WriteInfo($"One Relationship"); var oneRelationship = res_search_with_withDomain_type.Relationships[0]; printOneRelationship(oneRelationship.Id, oneRelationship.CreatedOn, oneRelationship.IsReadOnly, oneRelationship.IsService, oneRelationship.IsDeleted, oneRelationship.Entities[0].Domain, oneRelationship.Entities[0].Type, oneRelationship.Entities[0].Id, oneRelationship.Entities[1].Domain, oneRelationship.Entities[1].Type, oneRelationship.Entities[1].Id); } //intersect without withEntities IntersectRelationshipsRequest intersectReqBody = new IntersectRelationshipsRequest(); DomainEntity oneDomainEntity = new DomainEntity(); oneDomainEntity.Domain = "autodesk-bim360-modelcoordination"; oneDomainEntity.Type = "scope"; oneDomainEntity.Id = "2e905b04-5666-4a8d-a303-27807c132900"; intersectReqBody.Entities = new List <NewDomainEntity>(); intersectReqBody.Entities.Add(oneDomainEntity); var res_intersect_relationship = await relationshipClient.IntersectRelationshipsAsync(project_id_without_b, false, null, null, intersectReqBody); ColourConsole.WriteSuccess($"get intersect relationships [autodesk-bim360-modelcoordination & clashgroup & df0743c0-e1bb-11e9-96ff-ad6fd4c4196b]\n" + $"Count:{res_intersect_relationship.Relationships.Count}"); if (res_intersect_relationship != null && res_intersect_relationship.Relationships.Count > 0) { //dump one relationship data var oneRelationship = res_intersect_relationship.Relationships[0]; printOneRelationship(oneRelationship.Id, oneRelationship.CreatedOn, oneRelationship.IsReadOnly, oneRelationship.IsService, oneRelationship.IsDeleted, oneRelationship.Entities[0].Domain, oneRelationship.Entities[0].Type, oneRelationship.Entities[0].Id, oneRelationship.Entities[1].Domain, oneRelationship.Entities[1].Type, oneRelationship.Entities[1].Id); } //intersect with withEntities PartialDomainEntity oneWithDomainEntity = new PartialDomainEntity(); oneWithDomainEntity.Domain = "autodesk-bim360-issue"; oneWithDomainEntity.Type = "coordination"; oneWithDomainEntity.Id = "23733044-049d-4ee6-8add-8257248e116f"; intersectReqBody.WithEntities = new List <PartialDomainEntity>(); intersectReqBody.WithEntities.Add(oneWithDomainEntity); res_intersect_relationship = await relationshipClient.IntersectRelationshipsAsync(project_id_without_b, false, null, null, intersectReqBody); ColourConsole.WriteSuccess($"get intersect relationships [autodesk-bim360-modelcoordination & clashgroup & df0743c0-e1bb-11e9-96ff-ad6fd4c4196b]\n" + $" [autodesk-bim360-issue & coordination & 9b510ffb-d0c5-4c7d-91ba-044bdb0e77f0]\n" + $"Count:{res_intersect_relationship.Relationships.Count}"); if (res_intersect_relationship != null && res_intersect_relationship.Relationships.Count > 0) { //dump one relationship data var oneRelationship = res_intersect_relationship.Relationships[0]; printOneRelationship(oneRelationship.Id, oneRelationship.CreatedOn, oneRelationship.IsReadOnly, oneRelationship.IsService, oneRelationship.IsDeleted, oneRelationship.Entities[0].Domain, oneRelationship.Entities[0].Type, oneRelationship.Entities[0].Id, oneRelationship.Entities[1].Domain, oneRelationship.Entities[1].Type, oneRelationship.Entities[1].Id); } }
private static async Task RunAsync() { var configuration = new SampleConfiguration(); //----------------------------------------------------------------------------------------------------- // Sample Configuration //----------------------------------------------------------------------------------------------------- // Either add a .adsk-forge/SampleConfiguration.json file to the Environment.SpecialFolder.UserProfile // folder (this will be different on windows vs mac/linux) or pass the optional configuration // Dictionary<string, string> to set AuthToken, Account and Project values on SampleConfiguration // // configuration.Load(new Dictionary<string, string> // { // { "AuthToken", "Your Forge App OAuth token" }, // { "AccountId", "Your BIM 360 account GUID (no b. prefix)" }, // { "ProjectId", "Your BIM 360 project GUID (no b. prefix)"} // }); // // See: SampleConfigurationExtensions.cs for more information. //----------------------------------------------------------------------------------------------------- configuration.Load(); // create a service provider for IoC composition var serviceProvider = new ServiceCollection() .AddSampleForgeServices(configuration) .BuildServiceProvider(); // load the state from CreateModelSetSample var fileManager = serviceProvider.GetRequiredService <ILocalFileManager>(); var modelSetCreateSampleState = await fileManager.ReadJsonAsync <CreateModelSetSampleState>() ?? throw new InvalidOperationException("Could not load CreateModelSetSampleState, have you run CreateModelSetSample?"); // get the first page of model set views var modelSetClient = serviceProvider.GetRequiredService <IModelSetClient>(); ModelSetView sampleView = null; bool createSampleView = true; var views = await modelSetClient.GetModelSetViewsAsync( containerId : modelSetCreateSampleState.ModelSet.ContainerId, modelSetId : modelSetCreateSampleState.ModelSet.ModelSetId, pageLimit : null, continuationToken : null, createdBy : null, modifiedBy : null, after : null, before : null, isPrivate : null, sortBy : null, sortDirection : null); if (views?.ModelSetViews.Count > 0) { foreach (var view in views.ModelSetViews) { if (view.Name.Equals(SampleModelSetView.Name)) { createSampleView = false; sampleView = view; ColourConsole.WriteInfo($"Found sample view, {view.Name}, is private:{view.IsPrivate}"); } else { ColourConsole.WriteInfo($"Found, {view.Name}, is private:{view.IsPrivate}"); } } } else { ColourConsole.WriteInfo($"No views found for model set {modelSetCreateSampleState.ModelSet.ModelSetId}, create sample..."); } // if the sample view does not exist create it using the lineages we // lave on the current tip verison of the model set ModelSetVersion modelSetTipVersion = await modelSetClient.GetModelSetVersionLatestAsync( modelSetCreateSampleState.ModelSet.ContainerId, modelSetCreateSampleState.ModelSet.ModelSetId); if (createSampleView) { if (modelSetTipVersion != null && modelSetTipVersion?.DocumentVersions.Count > 1) { var lineages = modelSetTipVersion.DocumentVersions .Where(v => v.DocumentStatus == ModelSetDocumentStatus.Succeeded) .Take(2) .Select(d => d.DocumentLineage).ToList(); var modelSetView = new NewModelSetView { Name = SampleModelSetView.Name, Description = SampleModelSetView.Description, IsPrivate = true, Definition = lineages .Select( l => new LineageViewable { LineageUrn = l.LineageUrn }) .ToList() }; // this extension method wraps the job polling sampleView = await modelSetClient.CreateModelSetView( modelSetCreateSampleState.ModelSet.ContainerId, modelSetCreateSampleState.ModelSet.ModelSetId, modelSetView); ColourConsole.WriteSuccess($"Created sample view: {sampleView.Name}, is private: {sampleView.IsPrivate}"); } else { ColourConsole.WriteWarning($"No model set version with >= 2 lineages in {modelSetCreateSampleState.ModelSet.ModelSetId}, skip sample view create!"); } } // if we have a sample view toggle its privacy flag. If the view was created above ^^ // then this should make the sample view public, otherwise it will become private if (sampleView != null) { // this extension method wraps the job polling sampleView = await modelSetClient.UpdateModelSetView( modelSetCreateSampleState.ModelSet.ContainerId, modelSetCreateSampleState.ModelSet.ModelSetId, sampleView.ViewId, new UpdateModelSetView { OldIsPrivate = sampleView.IsPrivate, NewIsPrivate = !sampleView.IsPrivate }); ColourConsole.WriteSuccess($"Toggled sample view is private: {sampleView.IsPrivate}"); } // finally if the sample view exists, instance it against the tip if (sampleView != null) { var viewVersion = await modelSetClient.GetModelSetViewVersionAsync( modelSetCreateSampleState.ModelSet.ContainerId, modelSetTipVersion.ModelSetId, modelSetTipVersion.Version, sampleView.ViewId); foreach (var doc in viewVersion.DocumentVersions) { ColourConsole.WriteSuccess($"View member {doc.DisplayName} => {doc.VersionUrn}"); } } }
private static async Task RunAsync() { var configuration = new SampleConfiguration(); //----------------------------------------------------------------------------------------------------- // Sample Configuration //----------------------------------------------------------------------------------------------------- // Either add a .adsk-forge/SampleConfiguration.json file to the Environment.SpecialFolder.UserProfile // folder (this will be different on windows vs mac/linux) or pass the optional configuration // Dictionary<string, string> to set AuthToken, Account and Project values on SampleConfiguration // // configuration.Load(new Dictionary<string, string> // { // { "AuthToken", "Your Forge App OAuth token" }, // { "AccountId", "Your BIM 360 account GUID (no b. prefix)" }, // { "ProjectId", "Your BIM 360 project GUID (no b. prefix)"} // }); // // See: SampleConfigurationExtensions.cs for more information. //----------------------------------------------------------------------------------------------------- configuration.Load(); // create a service provider for IoC composition var serviceProvider = new ServiceCollection() .AddSampleForgeServices(configuration) .BuildServiceProvider(); // cache some local state for later... var state = new GetClashResultsSampleState(); // load the state from CreateModelSetSample var fileManager = serviceProvider.GetRequiredService <ILocalFileManager>(); var modelSetCreateSampleState = await fileManager.ReadJsonAsync <CreateModelSetSampleState>() ?? throw new InvalidOperationException("Could not load CreateModelSetSampleState, have you run CreateModelSetSample?"); state.Container = modelSetCreateSampleState.ModelSet.ContainerId; // load the clash tests for the model set we created in CreateModelSetSample // and try and find the latest clash test to the latest model set verison var clashClient = serviceProvider.GetRequiredService <IClashClient>(); var moelSetClashTests = await clashClient.GetModelSetClashTestsAsync(modelSetCreateSampleState.ModelSet.ContainerId, modelSetCreateSampleState.ModelSet.ModelSetId, null, null); if (moelSetClashTests.Tests.Count > 0) { foreach (var test in moelSetClashTests.Tests.OrderBy(t => t.ModelSetVersion)) { ColourConsole.WriteSuccess($"Test {test.ModelSetId}:{test.ModelSetVersion:00}; status {test.Status}; completed {test.CompletedOn?.ToString("u")}"); } state.Latest = moelSetClashTests.Tests.OrderBy(t => t.ModelSetVersion).Last(); } else { ColourConsole.WriteInfo($"No clash test result found for {modelSetCreateSampleState.ModelSet.ModelSetId}, try again later."); } // make sure we can load this clash test if (state.HasLatest) { _ = await clashClient.GetClashTestAsync(modelSetCreateSampleState.ModelSet.ContainerId, state.Latest.Id) ?? throw new InvalidOperationException($"Error getting model set clash test {state.Latest.Id}"); } else { ColourConsole.WriteInfo("No latest clash test skipping get model set clash test"); } // get the resources for the latest clash test if (state.HasLatest) { state.ResourceCollection = await clashClient.GetClashTestResourcesAsync(modelSetCreateSampleState.ModelSet.ContainerId, state.Latest.Id); if (state.ResourceCollection?.Resources.Count > 0) { foreach (var res in state.ResourceCollection.Resources) { ColourConsole.WriteSuccess($"Found clash resource {res.Type}"); } } else { ColourConsole.WriteInfo($"No resources found for latest clash test {state.Latest.Id}"); } } else { ColourConsole.WriteInfo("No latest clash test skipping get model set clash test resources"); } // download the reources for the latest clash test if (state.HasResources) { foreach (var resource in state.ResourceCollection.Resources) { var name = new Uri(resource.Url).Segments.Last(); var fout = fileManager.NewPath(name); ColourConsole.WriteInfo($"Download {fout.Name}"); await resource.DownloadClashTestResource(fout); state.LocalResourcePaths[resource.Url] = fout; ColourConsole.WriteSuccess($"Downloaded {fout.Name}"); } } // Query the results of the clash test if (state.HasResources) { var documentIndexFile = state.LocalResourcePaths.Values.Single(f => f.Name.Equals("scope-version-document.2.0.0.json.gz", StringComparison.OrdinalIgnoreCase)); var documentIndexReader = new ClashResultReader <ClashDocument>(documentIndexFile, true); var documentIndex = new Dictionary <int, string>(); await documentIndexReader.Read(doc => { documentIndex[doc.Index] = doc.Urn; return(Task.FromResult(true)); }); var clashResultFile = state.LocalResourcePaths.Values.Single(f => f.Name.Equals("scope-version-clash.2.0.0.json.gz", StringComparison.OrdinalIgnoreCase)); var clashIndex = new Dictionary <int, Clash>(); var clashReader = new ClashResultReader <Clash>(clashResultFile, true); await clashReader.Read(c => { clashIndex[c.Id] = c; return(Task.FromResult(true)); }); // Show counts for the different clash statuses foreach (var group in clashIndex.Values.GroupBy(c => c.Status)) { ColourConsole.WriteSuccess($"Clash count for status {group.Key}: {group.Count()}"); } // get the clsh instance details var clashInstanceFile = state.LocalResourcePaths.Values.Single(f => f.Name.Equals("scope-version-clash-instance.2.0.0.json.gz", StringComparison.OrdinalIgnoreCase)); var clashInstanceReader = new ClashResultReader <ClashInstance>(clashInstanceFile, true); var clashInstanceIndex = new Dictionary <int, ClashInstance>(); await clashInstanceReader.Read(ci => { clashInstanceIndex[ci.ClashId] = ci; return(Task.FromResult(true)); }); // pick a random clash an view it var rnd = new Random(Guid.NewGuid().GetHashCode()); var clash = clashIndex.Values.Skip(rnd.Next(0, clashIndex.Count - 1)).Take(1).Single(); ColourConsole.WriteSuccess($"Clash : {clash.Id}"); ColourConsole.WriteSuccess($"Left Document : {documentIndex[clashInstanceIndex[clash.Id].LeftDocumentIndex]}"); ColourConsole.WriteSuccess($"Left Stable Object ID : {clashInstanceIndex[clash.Id].LeftStableObjectId}"); ColourConsole.WriteSuccess($"Left LMV ID : {clashInstanceIndex[clash.Id].LeftLmvObjectId}"); ColourConsole.WriteSuccess($"Right Document : {documentIndex[clashInstanceIndex[clash.Id].RightDocumentIndex]}"); ColourConsole.WriteSuccess($"Right Stable Object ID : {clashInstanceIndex[clash.Id].RightStableObjectId}"); ColourConsole.WriteSuccess($"Right LMV ID : {clashInstanceIndex[clash.Id].RightLmvObjectId}"); } // save the state for use in subsequent samples var stateFile = await fileManager.WriteJsonAsync(state); ColourConsole.WriteSuccess($"Sample state written to {stateFile.FullName}"); }
private static async Task RunAsync() { var configuration = new SampleConfiguration(); //----------------------------------------------------------------------------------------------------- // Sample Configuration //----------------------------------------------------------------------------------------------------- // Either add a .adsk-forge/SampleConfiguration.json file to the Environment.SpecialFolder.UserProfile // folder (this will be different on windows vs mac/linux) or pass the optional configuration // Dictionary<string, string> to set AuthToken, Account and Project values on SampleConfiguration // // configuration.Load(new Dictionary<string, string> // { // { "AuthToken", "Your Forge App OAuth token" }, // { "AccountId", "Your BIM 360 account GUID (no b. prefix)" }, // { "ProjectId", "Your BIM 360 project GUID (no b. prefix)"} // }); // // See: SampleConfigurationExtensions.cs for more information. //----------------------------------------------------------------------------------------------------- configuration.Load(); // create a service provider for IoC composition var serviceProvider = new ServiceCollection() .AddSampleForgeServices(configuration) .BuildServiceProvider(); // load the state from GetClashResultsSample var fileManager = serviceProvider.GetRequiredService <ILocalFileManager>(); var clashResultSampleState = await fileManager.ReadJsonAsync <GetClashResultsSampleState>() ?? throw new InvalidOperationException("Could not load GetClashResultsSampleState.json, have you run GetClashResultsSample?"); // get the model set versoin associated with the clash test var modelSetClient = serviceProvider.GetRequiredService <IModelSetClient>(); var modelSetVersion = await modelSetClient.GetModelSetVersionAsync( clashResultSampleState.Container, clashResultSampleState.Latest.ModelSetId, clashResultSampleState.Latest.ModelSetVersion); ColourConsole.WriteSuccess($"Loaded model set version {clashResultSampleState.Latest.ModelSetId}:{clashResultSampleState.Latest.ModelSetVersion}"); // Get the first page of assigned clash groups AKA coordination issues. var clashClient = serviceProvider.GetRequiredService <IClashClient>(); var assignedClashGroups = await clashClient.GetClashTestAssignedClashGroupIntersectionAsync( clashResultSampleState.Container, clashResultSampleState.Latest.Id, null, null); ColourConsole.WriteSuccess($"Loaded page 1 of asigned clash issues with test context {clashResultSampleState.Latest.Id}"); // Get the details of the clash groups returned var assignedClashGroupDetails = await clashClient.GetAssignedClashGroupBatchAsync( clashResultSampleState.Container, clashResultSampleState.Latest.Id, false, assignedClashGroups.Groups.Select(cg => cg.Id)); ColourConsole.WriteSuccess($"Loaded {assignedClashGroups.Groups.Count} clash groups"); // get the index manifest and map the document URNs from the clash data to index seed file document keys var modelSetIndex = serviceProvider.GetRequiredService <IModelSetIndex>(); var indexManifest = await modelSetIndex.GetManifest( clashResultSampleState.Container, clashResultSampleState.Latest.ModelSetId, clashResultSampleState.Latest.ModelSetVersion) ?? throw new InvalidOperationException($"No indfex manifest found for {clashResultSampleState.Latest.ModelSetVersion}:{clashResultSampleState.Latest.ModelSetVersion}"); ColourConsole.WriteSuccess($"Loaded index manifest {clashResultSampleState.Latest.ModelSetId}:{clashResultSampleState.Latest.ModelSetVersion}"); // map of document version URN -> document index key var documentObjectIndexIdMap = modelSetVersion.DocumentVersions.ToDictionary( doc => doc.VersionUrn, doc => new IndexDocumentObjects { SeedFileVersionUrn = doc.OriginalSeedFileVersionUrn, DocumentVersionUrn = doc.VersionUrn, IndexFileKey = indexManifest.SeedFiles.Single(sf => sf.Urn.Equals(doc.OriginalSeedFileVersionUrn, StringComparison.OrdinalIgnoreCase)).Id, IndexDocumentKey = indexManifest.SeedFiles.SelectMany(sf => sf.Documents).Single(d => d.VersionUrn.Equals(doc.VersionUrn, StringComparison.OrdinalIgnoreCase)).Id }, StringComparer.OrdinalIgnoreCase); foreach (var kvp in documentObjectIndexIdMap) { ColourConsole.WriteInfo($"File {kvp.Value.IndexFileKey} contains document {kvp.Value.IndexDocumentKey}"); } // Grab all of the objects we are intrested in by getting the left and right LMV object IDs from the individual clashes. foreach (var clashGroupDetail in assignedClashGroupDetails) { var documentIdMap = clashGroupDetail.ClashData.Documents.ToDictionary(d => d.Id, d => d.Urn); foreach (var clashInstance in clashGroupDetail.ClashData.ClashInstances) { documentObjectIndexIdMap[documentIdMap[clashInstance.Ldid]].AddObjectId(clashInstance.Lvid); documentObjectIndexIdMap[documentIdMap[clashInstance.Rdid]].AddObjectId(clashInstance.Rvid); } } var rows = new List <IndexRow>(); foreach (var kvp in documentObjectIndexIdMap) { if (kvp.Value.Objects.Count == 0) { continue; } ColourConsole.WriteInfo($"Query file key {kvp.Value.IndexFileKey}, objects {string.Join(',', kvp.Value.Objects)}"); // get the objects in this seed file using WHERE IN - watch out for ovweflow // this might need to be chunked into multiple queries if you have lots of objects... string query = $"select * from s3object s where s.file = '{kvp.Value.IndexFileKey}' and s.id in (" + string.Join(',', kvp.Value.Objects) + ")"; ColourConsole.WriteInfo(query); var queryResults = await modelSetIndex.Query( clashResultSampleState.Container, clashResultSampleState.Latest.ModelSetId, clashResultSampleState.Latest.ModelSetVersion, query); ColourConsole.WriteSuccess($"Query results downloaded to {queryResults.FullName}"); // itterate over the results and pull out the rows var reader = new IndexResultReader(queryResults, null); var summary = await reader.ReadToEndAsync(obj => { rows.Add(obj); return(Task.FromResult(true)); }, false); } // get the issue container for this project var dataClient = serviceProvider.GetRequiredService <IForgeDataClient>(); dynamic obj = await dataClient.GetProjectAsJObject() ?? throw new InvalidOperationException($"Could not load prject {configuration.ProjectId}"); Guid issueContainer = obj.data.relationships.issues.data.id; var issueClient = serviceProvider.GetRequiredService <IForgeIssueClient>(); foreach (var clashGroupDetail in assignedClashGroupDetails) { dynamic issue = await issueClient.GetIssue(issueContainer, clashGroupDetail.IssueId); ColourConsole.WriteSuccess($"Issue : {issue.data.attributes.title}"); foreach (var clashInstance in clashGroupDetail.ClashData.ClashInstances) { var leftDocument = documentObjectIndexIdMap[clashGroupDetail.ClashData.Documents.Single(d => d.Id == clashInstance.Ldid).Urn]; var leftObject = rows.SingleOrDefault(r => r.Id == clashInstance.Lvid && r.DocumentIds.Contains(leftDocument.IndexDocumentKey)); var rightDocument = documentObjectIndexIdMap[clashGroupDetail.ClashData.Documents.Single(d => d.Id == clashInstance.Rdid).Urn]; var rightObject = rows.SingleOrDefault(r => r.Id == clashInstance.Rvid && r.DocumentIds.Contains(rightDocument.IndexDocumentKey)); ColourConsole.WriteInfo($" {(string)leftObject.Data["p153cb174"]} clashes with {(string)rightObject.Data["p153cb174"]}"); } } }
private static async Task RunAsync() { var configuration = new SampleConfiguration(); //----------------------------------------------------------------------------------------------------- // Sample Configuration //----------------------------------------------------------------------------------------------------- // Either add a .adsk-forge/SampleConfiguration.json file to the Environment.SpecialFolder.UserProfile // folder (this will be different on windows vs mac/linux) or pass the optional configuration // Dictionary<string, string> to set AuthToken, Account and Project values on SampleConfiguration // // configuration.Load(new Dictionary<string, string> // { // { "AuthToken", "Your Forge App OAuth token" }, // { "AccountId", "Your BIM 360 account GUID (no b. prefix)" }, // { "ProjectId", "Your BIM 360 project GUID (no b. prefix)"} // }); // // See: SampleConfigurationExtensions.cs for more information. //----------------------------------------------------------------------------------------------------- configuration.Load(); // create a service provider for IoC composition var serviceProvider = new ServiceCollection() .AddSampleForgeServices(configuration) .BuildServiceProvider(); var state = new CreateModelSetSampleState(); // find the project files folder var forgeDataClient = serviceProvider.GetRequiredService <IForgeDataClient>(); state.PlansFolder = await forgeDataClient.FindTopFolderByName("Plans") ?? throw new InvalidOperationException("Could not find Plans folder!"); ColourConsole.WriteSuccess($"Found project plans folder {state.PlansFolder.Id}"); // try and find the sample root folder MC_SAMPLE in the root of Plans, if not found create it. state.TestFolderRoot = await forgeDataClient.FindFolderByName(state.PlansFolder.Id, CreateModelSetSampleState.MC_SAMPLE_FOLDER_NAME); if (state.TestFolderRoot == null) { state.TestFolderRoot = await forgeDataClient.CreateFolder(state.PlansFolder.Id, CreateModelSetSampleState.MC_SAMPLE_FOLDER_NAME) ?? throw new InvalidOperationException($"Create {CreateModelSetSampleState.MC_SAMPLE_FOLDER_NAME} failed!"); } // Now that the MC sample root folder has been created make a new folder beneath this folder for this run // of this console application. This is just a MC_{UTD-DATA-NOW} folder. This is not a convention for // Model Coordination in general, it is just how this sample code is laid out. var testFolderName = $"MC_{DateTime.UtcNow.ToString("yyyyMMddHHmmss")}"; state.TestFolder = await forgeDataClient.CreateFolder(state.TestFolderRoot.Id, testFolderName) ?? throw new InvalidOperationException($"Create {testFolderName} failed!"); ColourConsole.WriteSuccess($"Created test folder {testFolderName}"); // Find the models that this sample code uploads into the test folder created above. This will trigger the // BIM 360 Docs extraction workflow for these files. The upload process has two phases, (1) sending the bytes // to OSS (Autodesk cloud bucket storage) and (2) registerig these OSS resources with Forge-DM to make them // accessable via BIM 360 Docs. var fileManager = serviceProvider.GetRequiredService <ILocalFileManager>(); state.Uploads.Add(new ForgeUpload { File = fileManager.GetPathToSampleModelFile(SampleModelSet.Audubon.V1, "Audubon_Architecture.rvt") }); state.Uploads.Add(new ForgeUpload { File = fileManager.GetPathToSampleModelFile(SampleModelSet.Audubon.V1, "Audubon_Structure.rvt") }); state.Uploads.Add(new ForgeUpload { File = fileManager.GetPathToSampleModelFile(SampleModelSet.Audubon.V1, "Audubon_Mechanical.rvt") }); // For each file :- // - Create an OSS storage location // - Uplaod the files to OSS in chunks // - Create the Item(and Version) representing the bytes via Forge - DM foreach (var upload in state.Uploads) { ColourConsole.WriteInfo($"Upload {upload.File.FullName}"); upload.Storage = await forgeDataClient.CreateOssStorage(state.TestFolder.Id, upload.File.Name) ?? throw new InvalidOperationException($"Crete OSS storage object for {upload.File.Name} failed!"); upload.Result = await forgeDataClient.Upload(upload.File, upload.Storage); await forgeDataClient.CreateItem(state.TestFolder.Id, upload.Storage.Id, upload.File.Name); ColourConsole.WriteSuccess($"Uploaded {upload.File.Name}"); } // create a model set for the new folder var modelSetClient = serviceProvider.GetRequiredService <IModelSetClient>(); state.ModelSet = await modelSetClient.CreateModelSet( configuration.ProjectId, state.TestFolder.Name, new ModelSetFolder[] { new ModelSetFolder { FolderUrn = state.TestFolder.Id } }); ColourConsole.WriteSuccess($"Created model set {state.ModelSet.ModelSetId}"); // save the state for use in subsequent samples var stateFile = await fileManager.WriteJsonAsync(state); ColourConsole.WriteSuccess($"Sample state written to {stateFile.FullName}"); }