/// <summary> /// Create a simple entity called 'TestSource' with a single attribute /// </summary> /// <param name="corpus"></param> /// <param name="manifestDefault"></param> /// <param name="localRoot"></param> /// <returns></returns> private CdmEntityDefinition CreateEntityTestSource(CdmCorpusDefinition corpus, CdmManifestDefinition manifestDefault, CdmFolderDefinition localRoot) { string entityName = "TestSource"; CdmEntityDefinition entityTestSource = corpus.MakeObject <CdmEntityDefinition>(CdmObjectType.EntityDef, entityName); { string attributeName = "TestAttribute"; CdmTypeAttributeDefinition entityTestAttribute = corpus.MakeObject <CdmTypeAttributeDefinition>(CdmObjectType.TypeAttributeDef, nameOrRef: attributeName, simpleNameRef: false); entityTestAttribute.DataType = corpus.MakeRef <CdmDataTypeReference>(CdmObjectType.DataTypeRef, refObj: "string", simpleNameRef: true); entityTestAttribute.Purpose = corpus.MakeRef <CdmPurposeReference>(CdmObjectType.PurposeRef, refObj: "hasA", simpleNameRef: true); entityTestAttribute.DisplayName = attributeName; entityTestSource.Attributes.Add(entityTestAttribute); } CdmDocumentDefinition entityTestSourceDoc = corpus.MakeObject <CdmDocumentDefinition>(CdmObjectType.DocumentDef, $"{entityName}.cdm.json", false); entityTestSourceDoc.Imports.Add(FoundationJsonPath); entityTestSourceDoc.Definitions.Add(entityTestSource); localRoot.Documents.Add(entityTestSourceDoc, entityTestSourceDoc.Name); manifestDefault.Entities.Add(entityTestSource); return(entityTestSource); }
public async Task TestTypeAttributeProj() { string testName = "TestTypeAttributeProj"; string entityName = "NewPerson"; CdmCorpusDefinition corpus = ProjectionTestUtils.GetCorpus(testName, testsSubpath); foreach (List <string> resOpt in resOptsCombinations) { await ProjectionTestUtils.LoadEntityForResolutionOptionAndSave(corpus, testName, testsSubpath, entityName, resOpt); } CdmEntityDefinition entity = await corpus.FetchObjectAsync <CdmEntityDefinition>($"local:/{entityName}.cdm.json/{entityName}"); CdmEntityDefinition resolvedEntity = await ProjectionTestUtils.GetResolvedEntity(corpus, entity, new List <string> { "referenceOnly" }); // Original set of attributes: ["PersonInfo"] Assert.AreEqual(2, resolvedEntity.Attributes.Count); Assert.AreEqual("PersonInfo", (resolvedEntity.Attributes[0] as CdmTypeAttributeDefinition).Name); CdmTypeAttributeDefinition supportingAttribute = resolvedEntity.Attributes[1] as CdmTypeAttributeDefinition; Assert.AreEqual("PersonInfo_display", supportingAttribute.Name); ValidateInSupportOfAttribute(supportingAttribute, "PersonInfo"); }
public void TestZeroMinimumCardinality() { string testName = "TestZeroMinimumCardinality"; CdmCorpusDefinition corpus = TestHelper.GetLocalCorpus(testsSubpath, testName); corpus.SetEventCallback(new EventCallback { Invoke = (CdmStatusLevel statusLevel, string message) => { Assert.Fail(message); } }, CdmStatusLevel.Warning); // Create Local Root Folder CdmFolderDefinition localRoot = corpus.Storage.FetchRootFolder("local"); // Create Manifest CdmManifestDefinition manifest = corpus.MakeObject <CdmManifestDefinition>(CdmObjectType.ManifestDef, "default"); localRoot.Documents.Add(manifest, "default.manifest.cdm.json"); string entityName = "TestEntity"; // Create Entity CdmEntityDefinition entity = corpus.MakeObject <CdmEntityDefinition>(CdmObjectType.EntityDef, entityName); entity.ExtendsEntity = corpus.MakeRef <CdmEntityReference>(CdmObjectType.EntityRef, "CdmEntity", true); // Create Entity Document CdmDocumentDefinition document = corpus.MakeObject <CdmDocumentDefinition>(CdmObjectType.DocumentDef, $"{entityName}.cdm.json", false); document.Definitions.Add(entity); localRoot.Documents.Add(document, document.Name); manifest.Entities.Add(entity); string attributeName = "testAttribute"; string attributeDataType = "string"; string attributePurpose = "hasA"; // Create Type Attribute CdmTypeAttributeDefinition attribute = corpus.MakeObject <CdmTypeAttributeDefinition>(CdmObjectType.TypeAttributeDef, nameOrRef: attributeName, simpleNameRef: false); attribute.DataType = corpus.MakeRef <CdmDataTypeReference>(CdmObjectType.DataTypeRef, refObj: attributeDataType, simpleNameRef: true); attribute.Purpose = corpus.MakeRef <CdmPurposeReference>(CdmObjectType.PurposeRef, refObj: attributePurpose, simpleNameRef: true); attribute.DisplayName = attributeName; if (entity != null) { entity.Attributes.Add(attribute); } attribute.Cardinality = new CardinalitySettings(attribute) { Minimum = "0", Maximum = "*" }; Assert.IsTrue(attribute.IsNullable == true); }
public async Task TestEntityProperties() { var testInputPath = TestHelper.GetInputFolderPath(testsSubpath, "TestEntityProperties"); CdmCorpusDefinition corpus = new CdmCorpusDefinition(); corpus.SetEventCallback(new EventCallback { Invoke = CommonDataModelLoader.ConsoleStatusReport }, CdmStatusLevel.Warning); corpus.Storage.Mount("local", new LocalAdapter(testInputPath)); corpus.Storage.DefaultNamespace = "local"; CdmEntityDefinition obj = await corpus.FetchObjectAsync <CdmEntityDefinition>("local:/entA.cdm.json/Entity A"); CdmTypeAttributeDefinition att = obj.Attributes[0] as CdmTypeAttributeDefinition; var result = att.AppliedTraits.AllItems.Find(x => x.NamedReference == "is.constrained"); Assert.IsNotNull(result); Assert.AreEqual(att.MaximumLength, 30); Assert.IsNull(att.MaximumValue); Assert.IsNull(att.MinimumValue); // removing the only argument should remove the trait att.MaximumLength = null; result = att.AppliedTraits.AllItems.Find(x => x.NamedReference == "is.constrained"); Assert.IsNull(att.MaximumLength); Assert.IsNull(result); }
/// <summary> /// Validates trait for this test class. /// </summary> /// <param name="attribute">The type attribute.</param> /// <param name="expectedAttrName">The expected attribute name.</param> /// <param name="haveTraitG4">Whether this attribute has "means.TraitG4".</param> /// <param name="doesNotExist">Whether this attribute has traits from <c traitGroupFilePath/>.</param> /// <returns></returns> private static void ValidateTrait(CdmTypeAttributeDefinition attribute, string expectedAttrName, bool haveTraitG4 = false, bool doesNotExist = false) { Assert.AreEqual(expectedAttrName, attribute.Name); if (!doesNotExist) { Assert.IsNotNull(attribute.AppliedTraits.Item("means.TraitG100")); Assert.IsNotNull(attribute.AppliedTraits.Item("means.TraitG200")); Assert.IsNull(attribute.AppliedTraits.Item("means.TraitG300")); Assert.IsNotNull(attribute.AppliedTraits.Item("means.TraitG400")); if (haveTraitG4) { CdmTraitReference traitG4 = (CdmTraitReference)attribute.AppliedTraits.Item("means.TraitG4"); Assert.IsNotNull(traitG4); Assert.AreEqual("5", traitG4.Arguments.FetchValue("precision")); Assert.AreEqual("15", traitG4.Arguments.FetchValue("scale")); } } else { Assert.IsNull(attribute.AppliedTraits.Item("means.TraitG100")); Assert.IsNull(attribute.AppliedTraits.Item("means.TraitG200")); Assert.IsNull(attribute.AppliedTraits.Item("means.TraitG300")); Assert.IsNull(attribute.AppliedTraits.Item("means.TraitG400")); Assert.IsNull(attribute.AppliedTraits.Item("means.TraitG4")); } }
/// <summary> /// Create a simple entity called 'TestSource' with a single attribute /// </summary> /// <param name="entityName"></param> /// <param name="attributesParams"></param> /// <returns></returns> public CdmEntityDefinition CreateBasicEntity(string entityName, List <TypeAttributeParam> attributesParams) { CdmEntityDefinition entity = Corpus.MakeObject <CdmEntityDefinition>(CdmObjectType.EntityDef, entityName); foreach (TypeAttributeParam attributesParam in attributesParams) { CdmTypeAttributeDefinition attribute = Corpus.MakeObject <CdmTypeAttributeDefinition>(CdmObjectType.TypeAttributeDef, nameOrRef: attributesParam.AttributeName, simpleNameRef: false); attribute.DataType = Corpus.MakeRef <CdmDataTypeReference>(CdmObjectType.DataTypeRef, refObj: attributesParam.AttributeDataType, simpleNameRef: true); attribute.Purpose = Corpus.MakeRef <CdmPurposeReference>(CdmObjectType.PurposeRef, refObj: attributesParam.AttributePurpose, simpleNameRef: true); attribute.DisplayName = attributesParam.AttributeName; entity.Attributes.Add(attribute); } CdmDocumentDefinition entityDoc = Corpus.MakeObject <CdmDocumentDefinition>(CdmObjectType.DocumentDef, $"{entityName}.cdm.json", false); entityDoc.Imports.Add(AllImportsDocName); entityDoc.Definitions.Add(entity); LocalStorageRoot.Documents.Add(entityDoc, entityDoc.Name); DefaultManifest.Entities.Add(entity); AllImports.Imports.Add(entity.InDocument.Name); return(entity); }
public void TestMaximum() { string testName = "TestMaximum"; CdmCorpusDefinition corpus = ProjectionTestUtils.GetLocalCorpus(testsSubpath, testName); corpus.SetEventCallback(new EventCallback { Invoke = (CdmStatusLevel statusLevel, string message) => { if (!message.Contains("CardinalitySettings | Invalid maximum cardinality Abc.")) { Assert.Fail($"Some unexpected failure - {message}!"); } } }, CdmStatusLevel.Warning); // Create Dummy Type Attribute CdmTypeAttributeDefinition attribute = corpus.MakeObject <CdmTypeAttributeDefinition>(CdmObjectType.TypeAttributeDef, nameOrRef: "dummyAttribute", simpleNameRef: false); attribute.Cardinality = new CardinalitySettings(attribute) { Maximum = "Abc" }; }
private void MapTableColumnsToCdmAttributes(Table table, CdmEntityDefinition entity) { foreach (Column column in table.Columns) { CdmTypeAttributeDefinition attribute = new CdmTypeAttributeDefinition(corpus.Ctx, column.Name); string attributeType = CdmSqlTypeMapper.Map(column.Type).ToString(); attribute.DataType = new CdmDataTypeReference(corpus.Ctx, attributeType, true); attribute.IsNullable = column.IsNullable; if (column.IsPrimaryKey) { attribute.Purpose = new CdmPurposeReference(corpus.Ctx, "identifiedBy", true); } if (column.Length.MaxSize > 0) { attribute.MaximumLength = column.Length.MaxSize; } ProcessColumnAnnotations(column, attribute); entity.Attributes.Add(attribute); } }
private void ProcessColumnAnnotations(Column column, CdmTypeAttributeDefinition attribute) { var columnProcessor = new ColumnAnnotationProcessor(corpus, resolver, attribute); foreach (var annotation in column.Annotations) { annotation.Process(columnProcessor); } }
/// <summary> /// Validates trait "has.expansionInfo.list" for array type. /// </summary> /// <param name="attribute">The type attribute.</param> /// <param name="expectedAttrName">The expected attribute name.</param> /// <param name="ordinal">The expected ordinal.</param> /// <param name="expansionName">The expected expansion name.</param> /// <param name="memberAttribute">The expected member attribute name.</param> /// <returns></returns> public static void ValidateExpansionInfoTrait(CdmTypeAttributeDefinition attribute, string expectedAttrName, int ordinal, string expansionName, string memberAttribute) { Assert.AreEqual(expectedAttrName, attribute.Name); CdmTraitReference trait = (CdmTraitReference)attribute.AppliedTraits.Item("has.expansionInfo.list"); Assert.IsNotNull(trait); Assert.AreEqual(trait.Arguments.FetchValue("expansionName"), expansionName); Assert.AreEqual(trait.Arguments.FetchValue("ordinal"), ordinal.ToString()); Assert.AreEqual(trait.Arguments.FetchValue("memberAttribute"), memberAttribute); }
public void TestTraitToUnknownDataFormat() { var cdmAttribute = new CdmTypeAttributeDefinition(new ResolveContext(new CdmCorpusDefinition(), null), "SomeAttribute"); cdmAttribute.AppliedTraits.Add("is.dataFormat.someRandomDataFormat"); var traitToPropertyMap = new TraitToPropertyMap(cdmAttribute); var dataFormat = traitToPropertyMap.TraitsToDataFormat(false); Assert.AreEqual(CdmDataFormat.Unknown, dataFormat); }
/// <summary> /// Applies the arrayExpansion operation to the entity attribute provided. /// It also takes care of applying a renameAttributes operation and optionally applying a addCountAttribute operation. /// </summary> /// <param name="entityAttr"></param> /// <param name="startOrdinal"></param> /// <param name="endOrdinal"></param> /// <param name="renameFormat"></param> /// <param name="countAttName"></param> static void ApplyArrayExpansion(CdmEntityAttributeDefinition entityAttr, int startOrdinal, int endOrdinal, string renameFormat, string countAttName) { var ctx = entityAttr.Ctx; CdmProjection projection = new CdmProjection(ctx) { Source = entityAttr.Entity, RunSequentially = true, // Link for the Condition property documentation. // https://docs.microsoft.com/en-us/common-data-model/sdk/convert-logical-entities-resolved-entities#condition Condition = "!normalized" }; entityAttr.Entity = new CdmEntityReference(ctx, projection, false); // Link for the ArrayExpansion operation documentation. // https://docs.microsoft.com/en-us/common-data-model/sdk/projections/arrayexpansion var arrExpansionOperation = new CdmOperationArrayExpansion(ctx) { StartOrdinal = startOrdinal, EndOrdinal = endOrdinal }; projection.Operations.Add(arrExpansionOperation); // Link for the RenameAttributes operation documentation. // https://docs.microsoft.com/en-us/common-data-model/sdk/projections/renameattributes // Doing an ArrayExpansion without a RenameAttributes afterwards will result in the expanded attributes being merged in the final resolved entity. // This is because ArrayExpansion does not rename the attributes it expands by default. The expanded attributes end up with the same name and gets merged. // Example: We expand A to A[1], A[2], A[3], but A[1], A[2], A[3] are still named "A". var renameAttrsOperation = new CdmOperationRenameAttributes(ctx) { RenameFormat = renameFormat }; projection.Operations.Add(renameAttrsOperation); if (countAttName != null) { var countAttribute = new CdmTypeAttributeDefinition(ctx, countAttName) { DataType = new CdmDataTypeReference(ctx, "integer", true) }; // Link for the AddCountAttribute operation documentation. // https://docs.microsoft.com/en-us/common-data-model/sdk/projections/addcountattribute // It is recommended, but not mandated, to be used with the ArrayExpansion operation to provide an ArrayExpansion a count attribute that // represents the total number of expanded elements. AddCountAttribute can also be used by itself. var addCountAttrOperation = new CdmOperationAddCountAttribute(ctx) { CountAttribute = countAttribute }; projection.Operations.Add(addCountAttrOperation); } }
public void TestTraitToJsonDataFormat() { var cdmAttribute = new CdmTypeAttributeDefinition(new ResolveContext(new CdmCorpusDefinition(), null), "SomeAttribute"); cdmAttribute.AppliedTraits.Add("is.dataFormat.array"); cdmAttribute.AppliedTraits.Add("means.content.text.JSON"); var traitToPropertyMap = new TraitToPropertyMap(cdmAttribute); var dataFormat = traitToPropertyMap.TraitsToDataFormat(false); Assert.AreEqual(CdmDataFormat.Json, dataFormat); }
public void CdmTypeAttributeDefinitionNotNull() { var generator = BuildCdmEntityGenerator(); var Attributename = "Name"; var table = new Table("Customer") .WithColumn(Attributename, SqlDbType.VarChar); CdmEntityDefinition entity = generator.GenerateEntity(table); CdmTypeAttributeDefinition attribute = entity.GetAttribute(Attributename); Assert.NotNull(attribute); }
public void CdmTypeAttributeDefinitionHasPrimaryKey(bool isPrimaryKey) { var generator = BuildCdmEntityGenerator(); var attributeName = "Name"; var table = new Table("Customer") .WithColumn(attributeName, SqlDbType.VarChar, isPrimaryKey: isPrimaryKey); CdmEntityDefinition entity = generator.GenerateEntity(table); CdmTypeAttributeDefinition attribute = entity.GetAttribute(attributeName); Assert.Equal(isPrimaryKey, attribute.IsPrimaryKey); }
public void CdmTypeAttributeDefinitionIsValid() { var generator = BuildCdmEntityGenerator(); var Attributename = "Name"; var table = new Table("Customer") .WithColumn(Attributename, SqlDbType.VarChar); CdmEntityDefinition entity = generator.GenerateEntity(table); CdmTypeAttributeDefinition attribute = entity.GetAttribute(Attributename); bool isValid = attribute.Validate(); Assert.True(isValid); }
/// <summary> /// Create a Type Attribute /// </summary> /// <returns></returns> public CdmTypeAttributeDefinition CreateTypeAttribute(string attributeName, string dataType, string purpose) { CdmDataTypeReference dataTypeRef = Corpus.MakeRef <CdmDataTypeReference>(CdmObjectType.DataTypeRef, dataType, simpleNameRef: false); CdmPurposeReference purposeRef = Corpus.MakeRef <CdmPurposeReference>(CdmObjectType.PurposeRef, purpose, simpleNameRef: false); CdmTypeAttributeDefinition attribute = Corpus.MakeObject <CdmTypeAttributeDefinition>(CdmObjectType.TypeAttributeDef, nameOrRef: attributeName, simpleNameRef: false); attribute.DataType = dataTypeRef; attribute.Purpose = purposeRef; return(attribute); }
/// <summary> /// Validates trait for map's value or key. /// </summary> /// <param name="attribute">The type attribute.</param> /// <param name="ordinal">The expected ordinal.</param> /// <param name="expansionName">The expected expansion name.</param> /// <param name="memberAttribute">The expected member attribute name.</param> /// <param name="isKey">Whether this is a key.</param> /// <returns></returns> private void ValidateAttributeTrait(CdmTypeAttributeDefinition attribute, string expectedAttrName, int ordinal, string expansionName, string memberAttribute = null, bool isKey = false) { Assert.AreEqual(expectedAttrName, attribute.Name); CdmTraitReference trait = (CdmTraitReference)attribute.AppliedTraits.Item(isKey ? "indicates.expansionInfo.mapKey" : "has.expansionInfo.mapValue"); Assert.IsNotNull(trait); Assert.AreEqual(trait.Arguments.FetchValue("expansionName"), expansionName); Assert.AreEqual(trait.Arguments.FetchValue("ordinal"), ordinal.ToString()); if (memberAttribute != null) { Assert.AreEqual(trait.Arguments.FetchValue("memberAttribute"), memberAttribute); } }
public async Task TestNonMaxDepthCached() { CdmCorpusDefinition cdmCorpus = TestHelper.GetLocalCorpus(testsSubpath, "TestMaxDepth"); CdmEntityDefinition aEnt = await cdmCorpus.FetchObjectAsync <CdmEntityDefinition>("A.cdm.json/A"); CdmEntityDefinition bEnt = await cdmCorpus.FetchObjectAsync <CdmEntityDefinition>("B.cdm.json/B"); CdmEntityDefinition cEnt = await cdmCorpus.FetchObjectAsync <CdmEntityDefinition>("C.cdm.json/C"); CdmEntityDefinition dEnt = await cdmCorpus.FetchObjectAsync <CdmEntityDefinition>("D.cdm.json/D"); // when resolving A, B should be cached and it should exclude any attributes from D because // it is outside of the maxDepth CdmEntityDefinition resA = await aEnt.CreateResolvedEntityAsync("resA", new ResolveOptions( aEnt.InDocument, new AttributeResolutionDirectiveSet(new HashSet <string> { "normalized", "structured" }) )); // ensure that when resolving B on its own, attributes from D are included CdmEntityDefinition resB = await bEnt.CreateResolvedEntityAsync("resB", new ResolveOptions( bEnt.InDocument, new AttributeResolutionDirectiveSet(new HashSet <string> { "normalized", "structured" }) )); // check the attributes found in D from resolving A CdmAttributeGroupDefinition bAttInA = ((CdmAttributeGroupDefinition)((CdmAttributeGroupReference)resA.Attributes[1]).ExplicitReference); CdmAttributeGroupDefinition cAttInA = ((CdmAttributeGroupDefinition)((CdmAttributeGroupReference)(bAttInA.Members[1])).ExplicitReference); CdmAttributeGroupDefinition dAttInA = ((CdmAttributeGroupDefinition)((CdmAttributeGroupReference)(cAttInA.Members[1])).ExplicitReference); Assert.AreEqual(dAttInA.Members.Count, 1); // check that the attribute in D is a foreign key attribute CdmTypeAttributeDefinition dIdAttFromA = (CdmTypeAttributeDefinition)(dAttInA.Members[0]); Assert.AreEqual(dIdAttFromA.Name, "dId"); Assert.IsNotNull(dIdAttFromA.AppliedTraits.Item("is.linkedEntity.identifier")); // check the attributes found in D from resolving B CdmAttributeGroupDefinition cAttInB = ((CdmAttributeGroupDefinition)((CdmAttributeGroupReference)resB.Attributes[1]).ExplicitReference); CdmAttributeGroupDefinition dAttInB = ((CdmAttributeGroupDefinition)((CdmAttributeGroupReference)(cAttInB.Members[1])).ExplicitReference); Assert.AreEqual(dAttInB.Members.Count, 2); // check that the attribute in D is not a foreign key attribute CdmTypeAttributeDefinition dIdAttFromB = (CdmTypeAttributeDefinition)(dAttInB.Members[0]); Assert.AreEqual(dIdAttFromB.Name, "dId"); Assert.IsNull(dIdAttFromB.AppliedTraits.Item("is.linkedEntity.identifier")); }
public void CdmTypeAttributeDefinitionHasDataType() { var generator = BuildCdmEntityGenerator(); var attributeName = "Name"; var attributeType = cdmCorpus.CreateDataType(CdmDataFormat.String); var table = new Table("Customer") .WithColumn(attributeName, SqlDbType.VarChar); CdmEntityDefinition entity = generator.GenerateEntity(table); CdmTypeAttributeDefinition attribute = entity.GetAttribute(attributeName); Assert.NotNull(attribute); Assert.Equal(attributeType.NamedReference, attribute.DataType.NamedReference); }
/// <summary> /// Applies the arrayExpansion operation to the entity attribute provided. /// It also takes care of applying a renameAttributes operation and optionally applying a addCountAttribute operation. /// </summary> /// <param name="entityAttr"></param> /// <param name="startOrdinal"></param> /// <param name="endOrdinal"></param> /// <param name="renameFormat"></param> /// <param name="countAttName"></param> static void ApplyArrayExpansion(CdmEntityAttributeDefinition entityAttr, int startOrdinal, int endOrdinal, string renameFormat, string countAttName) { var ctx = entityAttr.Ctx; CdmProjection projection = new CdmProjection(ctx) { Source = entityAttr.Entity, RunSequentially = true, // Link for the Condition property documentation. // https://docs.microsoft.com/en-us/common-data-model/sdk/convert-logical-entities-resolved-entities#condition Condition = "!normalized" }; entityAttr.Entity = new CdmEntityReference(ctx, projection, false); // Link for the ArrayExpansion operation documentation. // https://docs.microsoft.com/en-us/common-data-model/sdk/projections/arrayexpansion var arrExpansionOperation = new CdmOperationArrayExpansion(ctx) { StartOrdinal = startOrdinal, EndOrdinal = endOrdinal }; projection.Operations.Add(arrExpansionOperation); // Link for the RenameAttributes operation documentation. // https://docs.microsoft.com/en-us/common-data-model/sdk/projections/renameattributes var renameAttrsOperation = new CdmOperationRenameAttributes(ctx) { RenameFormat = renameFormat }; projection.Operations.Add(renameAttrsOperation); if (countAttName != null) { var countAttribute = new CdmTypeAttributeDefinition(ctx, countAttName) { DataType = new CdmDataTypeReference(ctx, "integer", true) }; // Link for the AddCountAttribute operation documentation. // https://docs.microsoft.com/en-us/common-data-model/sdk/projections/addcountattribute var addCountAttrOperation = new CdmOperationAddCountAttribute(ctx) { CountAttribute = countAttribute }; projection.Operations.Add(addCountAttrOperation); } }
public async Task TestModelJsonTypeAttributePersistence() { var corpus = TestHelper.GetLocalCorpus(testsSubpath, nameof(TestModelJsonTypeAttributePersistence)); // we need to create a second adapter to the output folder to fool the OM into thinking it's different // this is because there is a bug currently that prevents us from saving and then loading a model.json corpus.Storage.Mount("alternateOutput", new LocalAdapter(TestHelper.GetActualOutputFolderPath(testsSubpath, "TestModelJsonTypeAttributePersistence"))); // create manifest var entityName = "TestTypeAttributePersistence"; var localRoot = corpus.Storage.FetchRootFolder("local"); var outputRoot = corpus.Storage.FetchRootFolder("output"); var manifest = corpus.MakeObject <CdmManifestDefinition>(CdmObjectType.ManifestDef, "tempAbstract"); manifest.Imports.Add("cdm:/foundations.cdm.json", null); localRoot.Documents.Add(manifest); // create entity var doc = corpus.MakeObject <CdmDocumentDefinition>(CdmObjectType.DocumentDef, $"{entityName}.cdm.json"); doc.Imports.Add("cdm:/foundations.cdm.json", null); localRoot.Documents.Add(doc, doc.Name); var entityDef = doc.Definitions.Add(CdmObjectType.EntityDef, entityName) as CdmEntityDefinition; // create type attribute var cdmTypeAttributeDefinition = corpus.MakeObject <CdmTypeAttributeDefinition>(CdmObjectType.TypeAttributeDef, entityName, false); cdmTypeAttributeDefinition.IsReadOnly = true; entityDef.Attributes.Add(cdmTypeAttributeDefinition); manifest.Entities.Add(entityDef); var manifestResolved = await manifest.CreateResolvedManifestAsync("default", null); outputRoot.Documents.Add(manifestResolved); manifestResolved.Imports.Add("cdm:/foundations.cdm.json"); await manifestResolved.SaveAsAsync("model.json", true); var newManifest = await corpus.FetchObjectAsync <CdmManifestDefinition>("alternateOutput:/model.json"); CdmEntityDefinition newEnt = await corpus.FetchObjectAsync <CdmEntityDefinition>(newManifest.Entities[0].EntityPath, manifest); CdmTypeAttributeDefinition typeAttribute = newEnt.Attributes[0] as CdmTypeAttributeDefinition; Assert.IsTrue((bool)typeAttribute.IsReadOnly); }
public static DataColumn ToData(CdmTypeAttributeDefinition instance, CdmCorpusContext ctx, ResolveOptions resOpt, CopyOptions options) { var properties = CreateProperties(instance, resOpt, options); var originDataTypeName = new TypeInfo { Properties = properties, IsComplexType = false, IsNullable = instance.GetProperty("isNullable"), TypeFamily = "cdm" }; var t2pm = new TraitToPropertyMap(instance);; var numericTraits = t2pm.FetchTraitReference("is.dataFormat.numeric.shaped"); if (numericTraits != null) { foreach (var numericTraitsArg in numericTraits.Arguments) { if (numericTraitsArg.Name == "precision") { originDataTypeName.Precision = (int)numericTraitsArg.Value; } if (numericTraitsArg.Name == "scale") { originDataTypeName.Scale = (int)numericTraitsArg.Value; } } } var dataFormat = instance.GetProperty("dataFormat"); originDataTypeName = Utils.CdmDataFormatToSymsDataType(dataFormat, originDataTypeName); if (originDataTypeName.TypeName == null) { Logger.Error(ctx, Tag, nameof(ToData), instance.AtCorpusPath, CdmLogCode.ErrPersistSymsUnknownDataFormat, instance.DisplayName); return(null); } return(new DataColumn { OriginDataTypeName = originDataTypeName, Name = instance.Name }); }
/// <summary> /// Applies the replaceAsForeignKey and addAttributeGroup operations to the entity attribute provided. /// </summary> /// <param name="entityAttr"></param> /// <param name="fkAttrName"></param> /// <param name="attrGroupName"></param> static void ApplyDefaultBehavior(CdmEntityAttributeDefinition entityAttr, string fkAttrName, string attrGroupName) { var ctx = entityAttr.Ctx; CdmProjection projection = new CdmProjection(ctx) { // Link for the Source property documentation. // https://docs.microsoft.com/en-us/common-data-model/sdk/convert-logical-entities-resolved-entities#source Source = entityAttr.Entity, // Link for the RunSequentially property documentation. // https://docs.microsoft.com/en-us/common-data-model/sdk/convert-logical-entities-resolved-entities#run-sequentially RunSequentially = true }; entityAttr.Entity = new CdmEntityReference(ctx, projection, false); if (fkAttrName != null) { var foreignKeyAttr = new CdmTypeAttributeDefinition(ctx, fkAttrName) { DataType = new CdmDataTypeReference(ctx, "entityId", true) }; // Link for the ReplaceAsForeignKey operation documentation. // https://docs.microsoft.com/en-us/common-data-model/sdk/projections/replaceasforeignkey var replaceAsFKOperation = new CdmOperationReplaceAsForeignKey(ctx) { Condition = "referenceOnly", Reference = "addressLine", ReplaceWith = foreignKeyAttr }; projection.Operations.Add(replaceAsFKOperation); } if (attrGroupName != null) { // Link for the AddAttributeGroup operation documentation. // https://docs.microsoft.com/en-us/common-data-model/sdk/projections/addattributegroup var addAttrGroupOperation = new CdmOperationAddAttributeGroup(ctx) { Condition = "structured", AttributeGroupName = attrGroupName }; projection.Operations.Add(addAttrGroupOperation); } }
public void TestTypeAttributeSource() { CdmCorpusDefinition corpus = new CdmCorpusDefinition(); int errorCount = 0; corpus.SetEventCallback(new EventCallback() { Invoke = (level, message) => { errorCount++; } }, CdmStatusLevel.Error); CdmProjection projection = new CdmProjection(corpus.Ctx); CdmTypeAttributeDefinition _ = new CdmTypeAttributeDefinition(corpus.Ctx, "attribute") { Projection = projection }; // First case, a projection without source. projection.Validate(); Assert.AreEqual(0, errorCount); // Second case, a projection with a nested projection. CdmProjection innerProjection = new CdmProjection(corpus.Ctx); projection.Source = new CdmEntityReference(corpus.Ctx, innerProjection, false); projection.Validate(); innerProjection.Validate(); Assert.AreEqual(0, errorCount); // Third case, a projection with an explicit entity definition. innerProjection.Source = new CdmEntityReference(corpus.Ctx, new CdmEntityDefinition(corpus.Ctx, "Entity"), false); projection.Validate(); innerProjection.Validate(); Assert.AreEqual(1, errorCount); errorCount = 0; // Third case, a projection with a named reference. innerProjection.Source = new CdmEntityReference(corpus.Ctx, "Entity", false); projection.Validate(); innerProjection.Validate(); Assert.AreEqual(1, errorCount); }
public static void ValidateAttributesCollection(List <AttributeExpectedValue> expected, CdmCollection <CdmAttributeItem> actual) { Assert.AreEqual(expected.Count, actual.Count); for (int i = 0; i < actual.AllItems.Count; i++) { if (actual.AllItems[i].GetType() == typeof(CdmTypeAttributeDefinition)) { AttributeExpectedValue exp = (AttributeExpectedValue)expected[i]; CdmTypeAttributeDefinition act = (CdmTypeAttributeDefinition)actual.AllItems[i]; ValidateTypeAttributeDefinition(exp, act); } else if (actual.AllItems[i].GetType() == typeof(CdmAttributeGroupReference)) { AttributeExpectedValue exp = (AttributeExpectedValue)expected[i]; CdmAttributeGroupReference act = (CdmAttributeGroupReference)actual.AllItems[i]; ValidateAttributeGroupRef(exp, act); } } }
public async Task TestReadingIsPrimaryKey() { var testInputPath = TestHelper.GetInputFolderPath(testsSubpath, "TestReadingIsPrimaryKey"); CdmCorpusDefinition corpus = new CdmCorpusDefinition(); corpus.SetEventCallback(new EventCallback { Invoke = CommonDataModelLoader.ConsoleStatusReport }, CdmStatusLevel.Warning); corpus.Storage.Mount("local", new LocalAdapter(testInputPath)); corpus.Storage.DefaultNamespace = "local"; // Read from an unresolved entity schema. CdmEntityDefinition entity = await corpus.FetchObjectAsync <CdmEntityDefinition>("local:/TeamMembership.cdm.json/TeamMembership"); CdmAttributeGroupReference attributeGroupRef = (CdmAttributeGroupReference)entity.Attributes[0]; CdmAttributeGroupDefinition attributeGroup = (CdmAttributeGroupDefinition)attributeGroupRef.ExplicitReference; CdmTypeAttributeDefinition typeAttribute = (CdmTypeAttributeDefinition)attributeGroup.Members[0]; Assert.IsTrue((bool)typeAttribute.IsPrimaryKey); // Check that the trait "is.identifiedBy" is created with the correct argument. CdmTraitReference isIdentifiedBy1 = typeAttribute.AppliedTraits[1]; Assert.AreEqual("is.identifiedBy", isIdentifiedBy1.NamedReference); Assert.AreEqual("TeamMembership/(resolvedAttributes)/teamMembershipId", isIdentifiedBy1.Arguments[0].Value); // Read from a resolved entity schema. CdmEntityDefinition resolvedEntity = await corpus.FetchObjectAsync <CdmEntityDefinition>("local:/TeamMembership_Resolved.cdm.json/TeamMembership"); CdmTypeAttributeDefinition resolvedTypeAttribute = (CdmTypeAttributeDefinition)resolvedEntity.Attributes[0]; Assert.IsTrue((bool)resolvedTypeAttribute.IsPrimaryKey); // Check that the trait "is.identifiedBy" is created with the correct argument. CdmTraitReference isIdentifiedBy2 = resolvedTypeAttribute.AppliedTraits[6]; Assert.AreEqual("is.identifiedBy", isIdentifiedBy2.NamedReference); CdmAttributeReference argumentValue = isIdentifiedBy2.Arguments[0].Value; Assert.AreEqual("TeamMembership/(resolvedAttributes)/teamMembershipId", argumentValue.NamedReference); }
public static void ValidateAttributeGroupRef(AttributeExpectedValue expected, CdmAttributeGroupReference actual) { if (expected.AttributeGroupName != null || expected.Members != null) { if (actual.ExplicitReference != null) { CdmAttributeGroupDefinition actualObj = ((CdmAttributeGroupDefinition)actual.ExplicitReference); if (expected.AttributeGroupName != null) { Assert.AreEqual(expected.AttributeGroupName, actualObj.AttributeGroupName); } if (expected.AttributeContext != null) { Assert.AreEqual(expected.AttributeContext, actualObj.AttributeContext.NamedReference); } if (expected.Members != null) { Assert.AreEqual(expected.Members.Count, actualObj.Members.Count); for (int i = 0; i < actualObj.Members.Count; i++) { if (actualObj.Members[i].GetType() == typeof(CdmTypeAttributeDefinition)) { AttributeExpectedValue exp = (AttributeExpectedValue)expected.Members[i]; CdmTypeAttributeDefinition act = (CdmTypeAttributeDefinition)actualObj.Members[i]; ValidateTypeAttributeDefinition(exp, act); } else if (actualObj.Members[i].GetType() == typeof(CdmAttributeGroupReference)) { AttributeExpectedValue exp = (AttributeExpectedValue)expected.Members[i]; CdmAttributeGroupReference act = (CdmAttributeGroupReference)actualObj.Members[i]; ValidateAttributeGroupRef(exp, act); } else { throw new NotImplementedException("Unknown type!"); } } } } } }
public async Task TestReadingIsPrimaryKeyConstructedFromPurpose() { var testInputPath = TestHelper.GetInputFolderPath(testsSubpath, "TestReadingIsPrimaryKeyConstructedFromPurpose"); CdmCorpusDefinition corpus = new CdmCorpusDefinition(); corpus.SetEventCallback(new EventCallback { Invoke = CommonDataModelLoader.ConsoleStatusReport }, CdmStatusLevel.Warning); corpus.Storage.Mount("local", new LocalAdapter(testInputPath)); corpus.Storage.DefaultNamespace = "local"; CdmEntityDefinition entity = await corpus.FetchObjectAsync <CdmEntityDefinition>("local:/TeamMembership.cdm.json/TeamMembership"); CdmAttributeGroupReference attributeGroupRef = (CdmAttributeGroupReference)entity.Attributes[0]; CdmAttributeGroupDefinition attributeGroup = (CdmAttributeGroupDefinition)attributeGroupRef.ExplicitReference; CdmTypeAttributeDefinition typeAttribute = (CdmTypeAttributeDefinition)attributeGroup.Members[0]; Assert.AreEqual("identifiedBy", typeAttribute.Purpose.NamedReference); Assert.IsTrue((bool)typeAttribute.IsPrimaryKey); }
public static async Task <Attribute> ToData(CdmTypeAttributeDefinition instance, ResolveOptions resOpt, CopyOptions options) { var attribute = new Attribute { Name = instance.Name, DataType = DataTypeToData(instance.DataFormat), Description = instance.Description }; await Utils.ProcessAnnotationsToData(instance.Ctx, attribute, instance.AppliedTraits); var t2pm = new TraitToPropertyMap(instance); var isHiddenTrait = t2pm.FetchTraitReference("is.hidden"); if (isHiddenTrait != null) { attribute.IsHidden = true; } return(attribute); }