private void PrintDifference(DTInterfaceInfo dti, IEnumerable <DTRelationshipInfo> diffs) { Log.Alert($"Only in {dti.DisplayName.FirstOrDefault().Value ?? dti.Id.ToString()}"); Console.WriteLine(listFormatBoth, "Relationship Name", "Schema"); Console.WriteLine(listFormatBoth, "-----------------", "------"); foreach (var pi in diffs) { Console.WriteLine(listFormatBoth, pi.Name, pi.Target); } }
public void PrintInterfaceContent(DTInterfaceInfo dtif, IReadOnlyDictionary <Dtmi, DTEntityInfo> dtdlOM, int indent = 0) { var sb = new StringBuilder(); for (int i = 0; i < indent; i++) { sb.Append(" "); } Console.WriteLine($"{sb}Interface: {dtif.Id} | {dtif.DisplayName}"); Dictionary <string, DTContentInfo> contents = dtif.Contents; foreach (DTContentInfo item in contents.Values) { switch (item.EntityKind) { case DTEntityKind.Property: DTPropertyInfo pi = item as DTPropertyInfo; Console.WriteLine($"{sb}--Property: {pi.Name} with schema {pi.Schema}"); break; case DTEntityKind.Relationship: DTRelationshipInfo ri = item as DTRelationshipInfo; Console.WriteLine($"{sb}--Relationship: {ri.Name} with target {ri.Target}"); break; case DTEntityKind.Telemetry: DTTelemetryInfo ti = item as DTTelemetryInfo; Console.WriteLine($"{sb}--Telemetry: {ti.Name} with schema {ti.Schema}"); break; case DTEntityKind.Component: DTComponentInfo ci = item as DTComponentInfo; Console.WriteLine($"{sb}--Component: {ci.Id} | {ci.Name}"); DTInterfaceInfo component = ci.Schema; PrintInterfaceContent(component, dtdlOM, indent + 1); break; } } }
private static Dtmi DefiningModel(string item, DTInterfaceInfo ifInfo) { // must be depth first Dtmi result = null; foreach (DTInterfaceInfo parent in ifInfo.Extends) { result = DefiningModel(item, parent); if (result != null) { return(result); } } // Only check if defined locally after all super classes have been checked foreach (DTContentInfo ci in ifInfo.Contents.Values) { if (ci.Name == item) { return(ifInfo.Id); } } // This should really never happen return(null); }
public Task Run(Interactive p) { if (FirstModelId == null || SecondModelId == null) { Log.Error("Please specify two valid model ids as parameters"); return(Task.FromResult <object>(null)); } bool firstValid = false; bool secondValid = false; Dtmi first = ValidateAndCreateDtmi(FirstModelId); Dtmi second = ValidateAndCreateDtmi(SecondModelId); DTInterfaceInfo dt1 = null; DTInterfaceInfo dt2 = null; if (first != null && p.Models.TryGetValue(first, out dt1)) { firstValid = true; } if (second != null && p.Models.TryGetValue(second, out dt2)) { secondValid = true; } if (firstValid == false || secondValid == false) { if (first == null) { Log.Error($"First model not a valid dtmi"); } if (first != null && firstValid == false) { Log.Error($"First model not found in loaded models"); } if (second == null) { Log.Error($"Second model not a valid dtmi"); } if (second != null && secondValid == false) { Log.Error($"Second model not found in loaded models"); } return(Task.FromResult <object>(null)); } SortedDictionary <string, DTContentInfo> con1 = dt1.Contents; SortedDictionary <string, DTContentInfo> con2 = dt2.Contents; var props1 = con1 .Where(p => p.Value.EntityKind == DTEntityKind.Property) .Select(p => p.Value as DTPropertyInfo); var props2 = con2 .Where(p => p.Value.EntityKind == DTEntityKind.Property) .Select(p => p.Value as DTPropertyInfo); IEnumerable <DTPropertyInfo> duplicates = props1.Intersect(props2, new DTPropertyInfoComparer()); IEnumerable <DTPropertyInfo> diff1 = props1.Except(props2, new DTPropertyInfoComparer()); IEnumerable <DTPropertyInfo> diff2 = props2.Except(props1, new DTPropertyInfoComparer()); Log.Alert("Common Properties (comparing name and schema, ignoring explicit ids)"); Console.WriteLine(listFormatBoth, "Property Name", "Schema"); Console.WriteLine(listFormatBoth, "-------------", "------"); foreach (var pi in duplicates) { Console.WriteLine(listFormatBoth, pi.Name, pi.Schema); } Console.WriteLine(); PrintDifference(dt1, diff1); Console.WriteLine(); PrintDifference(dt2, diff2); var rels1 = con1 .Where(p => p.Value.EntityKind == DTEntityKind.Relationship) .Select(p => p.Value as DTRelationshipInfo); var rels2 = con2 .Where(p => p.Value.EntityKind == DTEntityKind.Relationship) .Select(p => p.Value as DTRelationshipInfo); IEnumerable <DTRelationshipInfo> dupRels = rels1.Intersect(rels2, new DTRelationshipInfoComparer()); IEnumerable <DTRelationshipInfo> diffRels1 = rels1.Except(rels2, new DTRelationshipInfoComparer()); IEnumerable <DTRelationshipInfo> diffRels2 = rels2.Except(rels1, new DTRelationshipInfoComparer()); Console.WriteLine(); Log.Alert("Common Relationships (comparing name and target - not checking properties, ignoring explicit ids)"); Console.WriteLine(listFormatBoth, "Relationship Name", "Target"); Console.WriteLine(listFormatBoth, "-----------------", "------"); foreach (var pi in dupRels) { string target = "<any>"; if (pi.Target != null) { target = pi.Target.ToString(); } Console.WriteLine(listFormatBoth, pi.Name, target); } Console.WriteLine(); PrintDifference(dt1, diffRels1); Console.WriteLine(); PrintDifference(dt2, diffRels2); return(Task.FromResult <object>(null)); }
private static void CreateCustomEntity(CdmCorpusDefinition cdmCorpus, CdmManifestDefinition manifestAbstract, CdmFolderDefinition localRoot, DTInterfaceInfo info) { string EntityName = info.Id.ToString(); string convertedEntityName = EntityName.Replace(':', '_'); convertedEntityName = convertedEntityName.Replace(';', '-'); // Create an entity - CustomAccount which has a relationship with the entity CustomPerson // Create the entity definition instance var entity = cdmCorpus.MakeObject <CdmEntityDefinition>(CdmObjectType.EntityDef, convertedEntityName, false); // Add type attributes to the entity instance var entityAttributeId = CreateEntityAttributeWithPurposeAndDataType(cdmCorpus, $"$dtId", "identifiedBy", "entityId"); entity.Attributes.Add(entityAttributeId); //var entityAttributeName = CreateEntityAttributeWithPurposeAndDataType(cdmCorpus, $"${convertedEntityName}Name", "hasA", "name"); //entity.Attributes.Add(entityAttributeName); var timestamp = CreateEntityAttributeWithPurposeAndDataType(cdmCorpus, "$timestamp", "hasA", "dateTime"); entity.Attributes.Add(timestamp); // Add properties to the entity instance entity.DisplayName = info.DisplayName.FirstOrDefault().Value; entity.Version = "0.0.1"; entity.Description = info.Description.FirstOrDefault().Value; // Create the document which contains the entity var entityDoc = cdmCorpus.MakeObject <CdmDocumentDefinition>(CdmObjectType.DocumentDef, $"{convertedEntityName}.cdm.json", false); // Add an import to the foundations doc so the traits about partitons will resolve nicely entityDoc.Imports.Add(FoundationJsonPath); entityDoc.Definitions.Add(entity); foreach (KeyValuePair <string, DTContentInfo> kvp in info.Contents) { if (kvp.Value.EntityKind == DTEntityKind.Property) { DTPropertyInfo pi = kvp.Value as DTPropertyInfo; Dtmi def = DefiningModel(pi.Name, info); if (def == info.Id) { Log.Out($"{info.Id}: Adding locally defined property {pi.Name}"); string type = ""; if (pi.Schema != null) { switch (pi.Schema.EntityKind) { case DTEntityKind.String: type = "string"; break; case DTEntityKind.Float: type = "float"; break; case DTEntityKind.Double: type = "double"; break; case DTEntityKind.Boolean: type = "boolean"; break; case DTEntityKind.Integer: type = "integer"; break; case DTEntityKind.DateTime: type = "dateTime"; break; default: break; } } if (type != "") { var prop = CreateEntityAttributeWithPurposeAndDataType(cdmCorpus, pi.Name, "hasA", type); entity.Attributes.Add(prop); } } else { Log.Alert($"{info.Id}: Ignored property {pi.Name} because it is defined in \n{def}"); } } } // Handle inheritance if (info.Extends.Count > 0) { foreach (DTInterfaceInfo parent in info.Extends) { string pEntityName = parent.Id.ToString(); string pConvertedEntityName = pEntityName.Replace(':', '_'); pConvertedEntityName = pConvertedEntityName.Replace(';', '-'); entity.ExtendsEntity = cdmCorpus.MakeObject <CdmEntityReference>(CdmObjectType.EntityRef, pConvertedEntityName, true); entityDoc.Imports.Add($"{pConvertedEntityName}.cdm.json"); } } // Handle references foreach (KeyValuePair <string, DTContentInfo> kvp in info.Contents) { if (kvp.Value.EntityKind == DTEntityKind.Relationship) { DTRelationshipInfo ri = kvp.Value as DTRelationshipInfo; Dtmi def = DefiningModel(ri.Name, info); if (def == info.Id) { string pEntityName = string.Format("{0}_{1}", def.AbsoluteUri.Substring(0, def.AbsoluteUri.IndexOf(";")), ri.Name.ToString()); string pConvertedEntityName = pEntityName.Replace(':', '_'); pConvertedEntityName = pConvertedEntityName.Replace(';', '-'); Log.Out($"{info.Id}: Adding locally defined relationship {ri.Name}"); var attributeExplanation = $"{ri.Name}: {ri.Description.Values.FirstOrDefault()}"; var t = kvp.Value; CreateRelatedCustomEntity(cdmCorpus, manifestAbstract, localRoot, ri.Properties, pConvertedEntityName, ri.Name); // You can all CreateSimpleAttributeForRelationshipBetweenTwoEntities() instead, but CreateAttributeForRelationshipBetweenTwoEntities() can show // more details of how to use resolution guidance to customize your data var refAttribute = CreateAttributeForRelationshipBetweenTwoEntities(cdmCorpus, convertedEntityName, pConvertedEntityName, attributeExplanation); entity.Attributes.Add(refAttribute); // Add an import to the foundations doc so the traits about partitons will resolve nicely entityDoc.Imports.Add(FoundationJsonPath); // the CustomAccount entity has a relationship with the CustomPerson entity, this relationship is defined from its attribute with traits, // the import to the entity reference CustomPerson's doc is required entityDoc.Imports.Add($"{pConvertedEntityName}.cdm.json"); } else { Log.Alert($"{info.Id}: Ignored property {ri.Name} because it is defined in \n{def}"); } } } // Add the document to the root of the local documents in the corpus localRoot.Documents.Add(entityDoc, entityDoc.Name); // Add the entity to the manifest manifestAbstract.Entities.Add(entity); }
private static void OrderInterface(OrderedHashSet <DTInterfaceInfo> orderedInterfaces, DTInterfaceInfo @interface) { // Order each extended interface. foreach (DTInterfaceInfo extendedInterface in @interface.Extends) { OrderInterface(orderedInterfaces, extendedInterface); } // Order each component schema interface. IEnumerable <DTInterfaceInfo> componentSchemas = from content in @interface.Contents.Values where content.EntityKind == DTEntityKind.Component select((DTComponentInfo)content).Schema; foreach (DTInterfaceInfo componentSchemaInterface in componentSchemas) { OrderInterface(orderedInterfaces, componentSchemaInterface); } // Add this interface to the list of ordered interfaces. if (!orderedInterfaces.Contains(@interface)) { orderedInterfaces.Add(@interface); } }