/// <inheritdoc /> internal override ProjectionAttributeStateSet AppendProjectionAttributeState( ProjectionContext projCtx, ProjectionAttributeStateSet projOutputSet, CdmAttributeContext attrCtx) { // Pass through all the input projection attribute states if there are any foreach (ProjectionAttributeState currentPAS in projCtx.CurrentAttributeStateSet.States) { projOutputSet.Add(currentPAS); } // Create a new attribute context for the operation AttributeContextParameters attrCtxOpAddSupportingAttrParam = new AttributeContextParameters { under = attrCtx, type = CdmAttributeContextType.OperationAddSupportingAttribute, Name = $"operation/index{Index}/{this.GetName()}" }; CdmAttributeContext attrCtxOpAddSupportingAttr = CdmAttributeContext.CreateChildUnder(projCtx.ProjectionDirective.ResOpt, attrCtxOpAddSupportingAttrParam); // Create a new attribute context for the supporting attribute we will create AttributeContextParameters attrCtxTypeAttrParam = new AttributeContextParameters { under = attrCtxOpAddSupportingAttr, type = CdmAttributeContextType.AddedAttributeSupporting, Name = this.SupportingAttribute.Name }; CdmAttributeContext attrCtxSupportingAttr = CdmAttributeContext.CreateChildUnder(projCtx.ProjectionDirective.ResOpt, attrCtxTypeAttrParam); // TODO: this if statement keeps the functionality the same way it works currently in resolution guidance. // This should be changed to point to the foreign key attribute instead. // There has to be some design decisions about how this will work and will be done in the next release. if (projCtx.CurrentAttributeStateSet.States.Count > 0) { ProjectionAttributeState lastState = projCtx.CurrentAttributeStateSet.States[projCtx.CurrentAttributeStateSet.States.Count - 1]; CdmTraitReference inSupportOfTrait = this.SupportingAttribute.AppliedTraits.Add("is.addedInSupportOf"); inSupportOfTrait.Arguments.Add("inSupportOf", lastState.CurrentResolvedAttribute.ResolvedName); } // Create the supporting attribute with the specified "SupportingAttribute" property as its target and apply the trait "is.virtual.attribute" to it List <string> addTrait = new List <string>() { "is.virtual.attribute" }; ResolvedAttribute newResAttr = CreateNewResolvedAttribute(projCtx, attrCtxSupportingAttr, this.SupportingAttribute, addedSimpleRefTraits: addTrait); // Create a new projection attribute state for the new supporting attribute and add it to the output set // There is no previous state for the newly created supporting attribute ProjectionAttributeState newPAS = new ProjectionAttributeState(projOutputSet.Ctx) { CurrentResolvedAttribute = newResAttr }; projOutputSet.Add(newPAS); return(projOutputSet); }
/// <inheritdoc /> internal override ProjectionAttributeStateSet AppendProjectionAttributeState( ProjectionContext projCtx, ProjectionAttributeStateSet projOutputSet, CdmAttributeContext attrCtx) { // Create a new attribute context for the operation AttributeContextParameters attrCtxOpAddAttrGroupParam = new AttributeContextParameters { under = attrCtx, type = CdmAttributeContextType.OperationAddAttributeGroup, Name = $"operation/index{Index}/{this.GetName()}" }; CdmAttributeContext attrCtxOpAddAttrGroup = CdmAttributeContext.CreateChildUnder(projCtx.ProjectionDirective.ResOpt, attrCtxOpAddAttrGroupParam); // Create a new attribute context for the attribute group we will create AttributeContextParameters attrCtxAttrGroupParam = new AttributeContextParameters { under = attrCtxOpAddAttrGroup, type = CdmAttributeContextType.AttributeDefinition, Name = this.AttributeGroupName }; CdmAttributeContext attrCtxAttrGroup = CdmAttributeContext.CreateChildUnder(projCtx.ProjectionDirective.ResOpt, attrCtxAttrGroupParam); // Create a new resolve attribute set builder that will be used to combine all the attributes into one set ResolvedAttributeSetBuilder rasb = new ResolvedAttributeSetBuilder(); // Iterate through all the projection attribute states generated from the source's resolved attributes // Each projection attribute state contains a resolved attribute that it is corresponding to foreach (ProjectionAttributeState currentPAS in projCtx.CurrentAttributeStateSet.States) { // Create a copy of the resolved attribute ResolvedAttribute resolvedAttribute = currentPAS.CurrentResolvedAttribute.Copy(); // Add the attribute to the resolved attribute set rasb.ResolvedAttributeSet.Merge(resolvedAttribute); // Add each attribute's attribute context to the resolved attribute set attribute context AttributeContextParameters AttrParam = new AttributeContextParameters { under = attrCtxAttrGroup, type = CdmAttributeContextType.AttributeDefinition, Name = resolvedAttribute.ResolvedName }; resolvedAttribute.AttCtx = CdmAttributeContext.CreateChildUnder(projCtx.ProjectionDirective.ResOpt, AttrParam); resolvedAttribute.AttCtx.AddLineage(currentPAS.CurrentResolvedAttribute.AttCtx); } // Create a new resolved attribute that will hold the attribute set containing all the attributes ResolvedAttribute resAttrNew = new ResolvedAttribute(projCtx.ProjectionDirective.ResOpt, rasb.ResolvedAttributeSet, this.AttributeGroupName, attrCtxAttrGroup); // Create a new projection attribute state pointing to the resolved attribute set that represents the attribute group ProjectionAttributeState newPAS = new ProjectionAttributeState(this.Ctx) { CurrentResolvedAttribute = resAttrNew }; projOutputSet.Add(newPAS); return(projOutputSet); }
private static ProjectionAttributeStateSet CreateNewProjectionAttributeStateSet( ProjectionContext projCtx, ProjectionAttributeStateSet projOutputSet, ResolvedAttribute newResAttrFK, string refAttrName) { List <ProjectionAttributeState> pasList = ProjectionResolutionCommonUtil.GetLeafList(projCtx, refAttrName); if (pasList != null) { // update the new foreign key resolved attribute with trait param with reference details ResolvedTrait reqdTrait = newResAttrFK.ResolvedTraits.Find(projCtx.ProjectionDirective.ResOpt, "is.linkedEntity.identifier"); if (reqdTrait != null) { CdmEntityReference traitParamEntRef = ProjectionResolutionCommonUtil.CreateForeignKeyLinkedEntityIdentifierTraitParameter(projCtx.ProjectionDirective, projOutputSet.Ctx.Corpus, pasList); reqdTrait.ParameterValues.SetParameterValue(projCtx.ProjectionDirective.ResOpt, "entityReferences", traitParamEntRef); } // Create new output projection attribute state set for FK and add prevPas as previous state set ProjectionAttributeState newProjAttrStateFK = new ProjectionAttributeState(projOutputSet.Ctx) { CurrentResolvedAttribute = newResAttrFK, PreviousStateList = pasList }; projOutputSet.Add(newProjAttrStateFK); } else { // Log error & return projOutputSet without any change Logger.Error(TAG, projOutputSet.Ctx, $"Unable to locate state for reference attribute \"{refAttrName}\".", nameof(CreateNewProjectionAttributeStateSet)); } return(projOutputSet); }
/// <inheritdoc /> internal override ProjectionAttributeStateSet AppendProjectionAttributeState( ProjectionContext projCtx, ProjectionAttributeStateSet projOutputSet, CdmAttributeContext attrCtx) { // Pass through all the input projection attribute states if there are any foreach (ProjectionAttributeState currentPAS in projCtx.CurrentAttributeStateSet.States) { projOutputSet.Add(currentPAS); } // Create a new attribute context for the operation AttributeContextParameters attrCtxOpAddTypeParam = new AttributeContextParameters { under = attrCtx, type = CdmAttributeContextType.OperationAddTypeAttribute, Name = $"operation/index{Index}/operationAddTypeAttribute" }; CdmAttributeContext attrCtxOpAddType = CdmAttributeContext.CreateChildUnder(projCtx.ProjectionDirective.ResOpt, attrCtxOpAddTypeParam); // Create a new attribute context for the Type attribute we will create AttributeContextParameters attrCtxTypeAttrParam = new AttributeContextParameters { under = attrCtxOpAddType, type = CdmAttributeContextType.AddedAttributeSelectedType, Name = "_selectedEntityName" }; CdmAttributeContext attrCtxTypeAttr = CdmAttributeContext.CreateChildUnder(projCtx.ProjectionDirective.ResOpt, attrCtxTypeAttrParam); // Create the Type attribute with the specified "typeAttribute" (from the operation) as its target and apply the trait "is.linkedEntity.name" to it List <string> addTrait = new List <string>() { "is.linkedEntity.name" }; ResolvedAttribute newResAttr = CreateNewResolvedAttribute(projCtx, attrCtxTypeAttr, this.TypeAttribute, addedSimpleRefTraits: addTrait); // Create a new projection attribute state for the new Type attribute and add it to the output set // There is no previous state for the newly created Type attribute ProjectionAttributeState newPAS = new ProjectionAttributeState(projOutputSet.Ctx) { CurrentResolvedAttribute = newResAttr }; projOutputSet.Add(newPAS); return(projOutputSet); }
/// <inheritdoc /> internal override ProjectionAttributeStateSet AppendProjectionAttributeState( ProjectionContext projCtx, ProjectionAttributeStateSet projOutputSet, CdmAttributeContext attrCtx) { // Create a new attribute context for the operation AttributeContextParameters attrCtxOpExcludeAttrsParam = new AttributeContextParameters { under = attrCtx, type = CdmAttributeContextType.OperationExcludeAttributes, Name = $"operation/index{Index}/operationExcludeAttributes" }; CdmAttributeContext attrCtxOpExcludeAttrs = CdmAttributeContext.CreateChildUnder(projCtx.ProjectionDirective.ResOpt, attrCtxOpExcludeAttrsParam); // Get the top-level attribute names of the attributes to exclude // We use the top-level names because the exclude list may contain a previous name our current resolved attributes had Dictionary <string, string> topLevelExcludeAttributeNames = ProjectionResolutionCommonUtil.GetTopList(projCtx, this.ExcludeAttributes); // Initialize a projection attribute context tree builder with the created attribute context for the operation ProjectionAttributeContextTreeBuilder attrCtxTreeBuilder = new ProjectionAttributeContextTreeBuilder(attrCtxOpExcludeAttrs); // Iterate through all the projection attribute states generated from the source's resolved attributes // Each projection attribute state contains a resolved attribute that it is corresponding to foreach (ProjectionAttributeState currentPAS in projCtx.CurrentAttributeStateSet.States) { // Check if the current projection attribute state's resolved attribute is in the list of attributes to exclude // If this attribute is not in the exclude list, then we are including it in the output if (!topLevelExcludeAttributeNames.ContainsKey(currentPAS.CurrentResolvedAttribute.ResolvedName)) { // Create the attribute context parameters and just store it in the builder for now // We will create the attribute contexts at the end attrCtxTreeBuilder.CreateAndStoreAttributeContextParameters(null, currentPAS, currentPAS.CurrentResolvedAttribute, CdmAttributeContextType.AttributeDefinition); // Create a projection attribute state for the included attribute by creating a copy of the current state // Copy() sets the current state as the previous state for the new one // We only create projection attribute states for attributes that are not in the exclude list ProjectionAttributeState newPAS = currentPAS.Copy(); projOutputSet.Add(newPAS); } else { // The current projection attribute state's resolved attribute is in the exclude list // Get the attribute name the way it appears in the exclude list string excludeAttributeName = null; topLevelExcludeAttributeNames.TryGetValue(currentPAS.CurrentResolvedAttribute.ResolvedName, out excludeAttributeName); // Create the attribute context parameters and just store it in the builder for now // We will create the attribute contexts at the end attrCtxTreeBuilder.CreateAndStoreAttributeContextParameters(excludeAttributeName, currentPAS, currentPAS.CurrentResolvedAttribute, CdmAttributeContextType.AttributeDefinition); } } // Create all the attribute contexts and construct the tree attrCtxTreeBuilder.ConstructAttributeContextTree(projCtx); return(projOutputSet); }
/// <summary> /// Pass through all the input projection attribute states if there are any. /// </summary> /// <param name="projCtx">The projection context.</param> /// <param name="projOutputSet">The projection attribute state set.</param> /// <returns></returns> private void AddAllPreviousAttributeStates(ProjectionContext projCtx, ProjectionAttributeStateSet projOutputSet) { // Pass through all the input projection attribute states if there are any foreach (ProjectionAttributeState currentPAS in projCtx.CurrentAttributeStateSet.States) { projOutputSet.Add(currentPAS); } }
/// <inheritdoc /> internal override ProjectionAttributeStateSet AppendProjectionAttributeState( ProjectionContext projCtx, ProjectionAttributeStateSet projOutputSet, CdmAttributeContext attrCtx) { // Create a new attribute context for the operation AttributeContextParameters attrCtxOpIncludeAttrsParam = new AttributeContextParameters { under = attrCtx, type = CdmAttributeContextType.OperationIncludeAttributes, Name = $"operation/index{Index}/operationIncludeAttributes" }; CdmAttributeContext attrCtxOpIncludeAttrs = CdmAttributeContext.CreateChildUnder(projCtx.ProjectionDirective.ResOpt, attrCtxOpIncludeAttrsParam); // Get the top-level attribute names for each of the included attributes // Since the include operation allows providing either current state resolved attribute names // or the previous state resolved attribute names, we search for the name in the PAS tree // and fetch the top level resolved attribute names. Dictionary <string, string> topLevelIncludeAttributeNames = ProjectionResolutionCommonUtil.GetTopList(projCtx, this.IncludeAttributes); // Initialize a projection attribute context tree builder with the created attribute context for the operation ProjectionAttributeContextTreeBuilder attrCtxTreeBuilder = new ProjectionAttributeContextTreeBuilder(attrCtxOpIncludeAttrs); // Iterate through all the PAS in the PASSet generated from the projection source's resolved attributes foreach (ProjectionAttributeState currentPAS in projCtx.CurrentAttributeStateSet.States) { // Check if the current PAS's RA is in the list of attributes to include. if (topLevelIncludeAttributeNames.ContainsKey(currentPAS.CurrentResolvedAttribute.ResolvedName)) { // Get the attribute name the way it appears in the include list string includeAttributeName = null; topLevelIncludeAttributeNames.TryGetValue(currentPAS.CurrentResolvedAttribute.ResolvedName, out includeAttributeName); // Create the attribute context parameters and just store it in the builder for now // We will create the attribute contexts at the end attrCtxTreeBuilder.CreateAndStoreAttributeContextParameters(includeAttributeName, currentPAS, currentPAS.CurrentResolvedAttribute, CdmAttributeContextType.AttributeDefinition); // Create a projection attribute state for the included attribute by creating a copy of the current state // Copy() sets the current state as the previous state for the new one // We only create projection attribute states for attributes in the include list ProjectionAttributeState newPAS = currentPAS.Copy(); projOutputSet.Add(newPAS); } else { // Create the attribute context parameters and just store it in the builder for now // We will create the attribute contexts at the end attrCtxTreeBuilder.CreateAndStoreAttributeContextParameters(null, currentPAS, currentPAS.CurrentResolvedAttribute, CdmAttributeContextType.AttributeDefinition); } } // Create all the attribute contexts and construct the tree attrCtxTreeBuilder.ConstructAttributeContextTree(projCtx); return(projOutputSet); }
/// <summary> /// Create a new artifact attribute and add it to the projOutputSet. /// </summary> /// <param name="projCtx">The projection context.</param> /// <param name="projOutputSet">The projection attribute state set.</param> /// <param name="attrCtx">The attribute context.</param> /// <returns></returns> private void AddNewArtifactAttributeState(ProjectionContext projCtx, ProjectionAttributeStateSet projOutputSet, CdmAttributeContext attrCtx) { // Create a new attribute context for the operation AttributeContextParameters attrCtxOpAddArtifactAttrParam = new AttributeContextParameters { under = attrCtx, type = CdmAttributeContextType.OperationAddArtifactAttribute, Name = $"operation/index{Index}/{this.GetName()}" }; CdmAttributeContext attrCtxOpAddArtifactAttr = CdmAttributeContext.CreateChildUnder(projCtx.ProjectionDirective.ResOpt, attrCtxOpAddArtifactAttrParam); if (this.NewAttribute is CdmTypeAttributeDefinition) { // Create a new attribute context for the new artifact attribute we will create AttributeContextParameters attrCtxNewAttrParam = new AttributeContextParameters { under = attrCtxOpAddArtifactAttr, type = CdmAttributeContextType.AddedAttributeNewArtifact, Name = this.NewAttribute.FetchObjectDefinitionName() }; CdmAttributeContext attrCtxNewAttr = CdmAttributeContext.CreateChildUnder(projCtx.ProjectionDirective.ResOpt, attrCtxNewAttrParam); ResolvedAttribute newResAttr = CreateNewResolvedAttribute(projCtx, attrCtxNewAttr, (CdmAttribute)this.NewAttribute); // Create a new projection attribute state for the new artifact attribute and add it to the output set // There is no previous state for the newly created attribute ProjectionAttributeState newPAS = new ProjectionAttributeState(projOutputSet.Ctx) { CurrentResolvedAttribute = newResAttr }; projOutputSet.Add(newPAS); } else if (this.NewAttribute is CdmEntityAttributeDefinition || this.NewAttribute is CdmAttributeGroupReference) { var typeStr = this.NewAttribute is CdmEntityAttributeDefinition ? "an entity attribute" : "an attribute group"; Logger.Warning(this.Ctx, Tag, nameof(AppendProjectionAttributeState), this.AtCorpusPath, CdmLogCode.WarnProjAddArtifactAttrNotSupported, typeStr); } else { Logger.Error(this.Ctx, Tag, nameof(AppendProjectionAttributeState), this.AtCorpusPath, CdmLogCode.ErrProjUnsupportedSource, this.NewAttribute.ObjectType.ToString(), this.GetName()); } }
private static ProjectionAttributeStateSet CreateNewProjectionAttributeStateSet( ProjectionContext projCtx, ProjectionAttributeStateSet projOutputSet, ResolvedAttribute newResAttrFK, string refAttrName) { List <ProjectionAttributeState> pasList = ProjectionResolutionCommonUtil.GetLeafList(projCtx, refAttrName); string sourceEntity = projCtx.ProjectionDirective.OriginalSourceAttributeName; if (sourceEntity == null) { Logger.Warning(projOutputSet.Ctx, Tag, nameof(CreateNewProjectionAttributeStateSet), null, CdmLogCode.WarnProjFKWithoutSourceEntity, refAttrName); } if (pasList != null) { // update the new foreign key resolved attribute with trait param with reference details ResolvedTrait reqdTrait = newResAttrFK.ResolvedTraits.Find(projCtx.ProjectionDirective.ResOpt, "is.linkedEntity.identifier"); if (reqdTrait != null && sourceEntity != null) { CdmEntityReference traitParamEntRef = ProjectionResolutionCommonUtil.CreateForeignKeyLinkedEntityIdentifierTraitParameter(projCtx.ProjectionDirective, projOutputSet.Ctx.Corpus, pasList); reqdTrait.ParameterValues.SetParameterValue(projCtx.ProjectionDirective.ResOpt, "entityReferences", traitParamEntRef); } // Create new output projection attribute state set for FK and add prevPas as previous state set ProjectionAttributeState newProjAttrStateFK = new ProjectionAttributeState(projOutputSet.Ctx) { CurrentResolvedAttribute = newResAttrFK, PreviousStateList = pasList }; projOutputSet.Add(newProjAttrStateFK); } else { // Log error & return projOutputSet without any change Logger.Error(projOutputSet.Ctx, Tag, nameof(CreateNewProjectionAttributeStateSet), null, CdmLogCode.ErrProjRefAttrStateFailure, refAttrName); } return(projOutputSet); }
/// <inheritdoc /> internal override ProjectionAttributeStateSet AppendProjectionAttributeState( ProjectionContext projCtx, ProjectionAttributeStateSet projOutputSet, CdmAttributeContext attrCtx) { // Create a new attribute context for the operation AttributeContextParameters attrCtxOpCombineAttrsParam = new AttributeContextParameters { under = attrCtx, type = CdmAttributeContextType.OperationCombineAttributes, Name = $"operation/index{Index}/operationCombineAttributes" }; CdmAttributeContext attrCtxOpCombineAttrs = CdmAttributeContext.CreateChildUnder(projCtx.ProjectionDirective.ResOpt, attrCtxOpCombineAttrsParam); // Initialize a projection attribute context tree builder with the created attribute context for the operation ProjectionAttributeContextTreeBuilder attrCtxTreeBuilder = new ProjectionAttributeContextTreeBuilder(attrCtxOpCombineAttrs); // Get all the leaf level PAS nodes from the tree for each selected attribute and cache to a dictionary Dictionary <string, List <ProjectionAttributeState> > leafLevelCombineAttributeNames = new Dictionary <string, List <ProjectionAttributeState> >(); // Also, create a single list of leaf level PAS List <ProjectionAttributeState> leafLevelMergePASList = new List <ProjectionAttributeState>(); foreach (string select in this.Select) { List <ProjectionAttributeState> leafLevelListForCurrentSelect = ProjectionResolutionCommonUtil.GetLeafList(projCtx, select); if (leafLevelListForCurrentSelect != null && leafLevelListForCurrentSelect.Count > 0 && !leafLevelCombineAttributeNames.ContainsKey(select)) { leafLevelCombineAttributeNames.Add(select, leafLevelListForCurrentSelect); leafLevelMergePASList.AddRange(leafLevelListForCurrentSelect); } } // Create a List of top-level PAS objects that will be get merged based on the selected attributes List <ProjectionAttributeState> pasMergeList = new List <ProjectionAttributeState>(); // Run through the top-level PAS objects foreach (ProjectionAttributeState currentPAS in projCtx.CurrentAttributeStateSet.States) { if (leafLevelCombineAttributeNames.ContainsKey(currentPAS.CurrentResolvedAttribute.ResolvedName)) { // Attribute to Merge if (!pasMergeList.Contains(currentPAS)) { pasMergeList.Add(currentPAS); } } else { // Attribute to Pass Through // Create a projection attribute state for the non-selected / pass-through attribute by creating a copy of the current state // Copy() sets the current state as the previous state for the new one ProjectionAttributeState newPAS = currentPAS.Copy(); projOutputSet.Add(newPAS); } } if (pasMergeList.Count > 0) { CdmTypeAttributeDefinition mergeIntoAttribute = this.MergeInto as CdmTypeAttributeDefinition; // the merged attribute needs one new place to live, so here it is AttributeContextParameters mergedAttrCtxParam = new AttributeContextParameters { under = attrCtxOpCombineAttrs, type = CdmAttributeContextType.AttributeDefinition, Name = mergeIntoAttribute.GetName() }; CdmAttributeContext mergedAttrCtx = CdmAttributeContext.CreateChildUnder(projCtx.ProjectionDirective.ResOpt, mergedAttrCtxParam); // Create new resolved attribute, set the new attribute as target ResolvedAttribute raNewMergeInto = CreateNewResolvedAttribute(projCtx, mergedAttrCtx, mergeIntoAttribute, null); // Create new output projection attribute state set ProjectionAttributeState newMergeIntoPAS = new ProjectionAttributeState(projOutputSet.Ctx) { CurrentResolvedAttribute = raNewMergeInto, PreviousStateList = pasMergeList }; // Create the attribute context parameters and just store it in the builder for now // We will create the attribute contexts at the end foreach (string select in leafLevelCombineAttributeNames.Keys) { if (leafLevelCombineAttributeNames.ContainsKey(select) && leafLevelCombineAttributeNames[select] != null && leafLevelCombineAttributeNames[select].Count > 0) { foreach (ProjectionAttributeState leafLevelForSelect in leafLevelCombineAttributeNames[select]) { attrCtxTreeBuilder.CreateAndStoreAttributeContextParameters(select, leafLevelForSelect, newMergeIntoPAS.CurrentResolvedAttribute, CdmAttributeContextType.AttributeDefinition, leafLevelForSelect.CurrentResolvedAttribute.AttCtx, // lineage is the source att newMergeIntoPAS.CurrentResolvedAttribute.AttCtx); // merge into points back here } } } projOutputSet.Add(newMergeIntoPAS); } // Create all the attribute contexts and construct the tree attrCtxTreeBuilder.ConstructAttributeContextTree(projCtx); return(projOutputSet); }
/// <inheritdoc /> internal override ProjectionAttributeStateSet AppendProjectionAttributeState( ProjectionContext projCtx, ProjectionAttributeStateSet projOutputSet, CdmAttributeContext attrCtx) { // Create a new attribute context for the operation AttributeContextParameters attrCtxOpArrayExpansionParam = new AttributeContextParameters { under = attrCtx, type = CdmAttributeContextType.OperationArrayExpansion, Name = $"operation/index{Index}/operationArrayExpansion" }; CdmAttributeContext attrCtxOpArrayExpansion = CdmAttributeContext.CreateChildUnder(projCtx.ProjectionDirective.ResOpt, attrCtxOpArrayExpansionParam); // Expansion steps start at round 0 int round = 0; List <ProjectionAttributeState> projAttrStatesFromRounds = new List <ProjectionAttributeState>(); // Ordinal validation if (this.StartOrdinal > this.EndOrdinal) { Logger.Warning(TAG, this.Ctx, $"startOrdinal {this.StartOrdinal} should not be greater than endOrdinal {this.EndOrdinal}", nameof(AppendProjectionAttributeState)); } else { // Ordinals should start at startOrdinal or 0, whichever is larger. int startingOrdinal = Math.Max(0, (int)this.StartOrdinal); // Ordinals should end at endOrdinal or the maximum ordinal allowed (set in resolve options), whichever is smaller. if (this.EndOrdinal > projCtx.ProjectionDirective.ResOpt.MaxOrdinalForArrayExpansion) { Logger.Warning(TAG, this.Ctx, $"endOrdinal {this.EndOrdinal} is greater than the maximum allowed ordinal of {projCtx.ProjectionDirective.ResOpt.MaxOrdinalForArrayExpansion}. Using the maximum allowed ordinal instead.", nameof(AppendProjectionAttributeState)); } int endingOrdinal = Math.Min(projCtx.ProjectionDirective.ResOpt.MaxOrdinalForArrayExpansion, (int)this.EndOrdinal); // For each ordinal, create a copy of the input resolved attribute for (int i = startingOrdinal; i <= endingOrdinal; i++) { // Create a new attribute context for the round AttributeContextParameters attrCtxRoundParam = new AttributeContextParameters { under = attrCtxOpArrayExpansion, type = CdmAttributeContextType.GeneratedRound, Name = $"_generatedAttributeRound{round}" }; CdmAttributeContext attrCtxRound = CdmAttributeContext.CreateChildUnder(projCtx.ProjectionDirective.ResOpt, attrCtxRoundParam); // Iterate through all the projection attribute states generated from the source's resolved attributes // Each projection attribute state contains a resolved attribute that it is corresponding to foreach (ProjectionAttributeState currentPAS in projCtx.CurrentAttributeStateSet.States) { // Create a new attribute context for the expanded attribute with the current ordinal AttributeContextParameters attrCtxExpandedAttrParam = new AttributeContextParameters { under = attrCtxRound, type = CdmAttributeContextType.AttributeDefinition, Name = $"{currentPAS.CurrentResolvedAttribute.ResolvedName}@{i}" }; CdmAttributeContext attrCtxExpandedAttr = CdmAttributeContext.CreateChildUnder(projCtx.ProjectionDirective.ResOpt, attrCtxExpandedAttrParam); if (currentPAS.CurrentResolvedAttribute.Target is ResolvedAttributeSet) { Logger.Error(TAG, this.Ctx, "Array expansion operation does not support attribute groups."); projAttrStatesFromRounds.Clear(); break; } // Create a new resolved attribute for the expanded attribute ResolvedAttribute newResAttr = CreateNewResolvedAttribute(projCtx, attrCtxExpandedAttr, currentPAS.CurrentResolvedAttribute.Target, currentPAS.CurrentResolvedAttribute.ResolvedName); newResAttr.AttCtx.AddLineage(currentPAS.CurrentResolvedAttribute.AttCtx); // Create a projection attribute state for the expanded attribute ProjectionAttributeState newPAS = new ProjectionAttributeState(projOutputSet.Ctx) { CurrentResolvedAttribute = newResAttr, PreviousStateList = new List <ProjectionAttributeState> { currentPAS }, Ordinal = i }; projAttrStatesFromRounds.Add(newPAS); } if (i == endingOrdinal) { break; } // Increment the round round++; } } if (projAttrStatesFromRounds.Count == 0) { // No rounds were produced from the array expansion - input passes through foreach (ProjectionAttributeState pas in projCtx.CurrentAttributeStateSet.States) { projOutputSet.Add(pas); } } else { // Add all the projection attribute states containing the expanded attributes to the output foreach (ProjectionAttributeState pas in projAttrStatesFromRounds) { projOutputSet.Add(pas); } } return(projOutputSet); }
/// <inheritdoc /> internal override ProjectionAttributeStateSet AppendProjectionAttributeState( ProjectionContext projCtx, ProjectionAttributeStateSet projOutputSet, CdmAttributeContext attrCtx) { // Create a new attribute context for the operation AttributeContextParameters attrCtxOpAlterTraitsParam = new AttributeContextParameters { under = attrCtx, type = CdmAttributeContextType.OperationAlterTraits, Name = $"operation/index{Index}/{this.GetName()}" }; CdmAttributeContext attrCtxOpAlterTraits = CdmAttributeContext.CreateChildUnder(projCtx.ProjectionDirective.ResOpt, attrCtxOpAlterTraitsParam); // Get the top-level attribute names of the selected attributes to apply // We use the top-level names because the applyTo list may contain a previous name our current resolved attributes had Dictionary <string, string> topLevelSelectedAttributeNames = this.ApplyTo != null?ProjectionResolutionCommonUtil.GetTopList(projCtx, this.ApplyTo) : null; foreach (ProjectionAttributeState currentPAS in projCtx.CurrentAttributeStateSet.States) { // Check if the current projection attribute state's resolved attribute is in the list of selected attributes // If this attribute is not in the list, then we are including it in the output without changes if (topLevelSelectedAttributeNames == null || topLevelSelectedAttributeNames.ContainsKey(currentPAS.CurrentResolvedAttribute.ResolvedName)) { // Create a new attribute context for the new attribute we will create AttributeContextParameters attrCtxNewAttrParam = new AttributeContextParameters { under = attrCtxOpAlterTraits, type = CdmAttributeContextType.AttributeDefinition, Name = currentPAS.CurrentResolvedAttribute.ResolvedName }; CdmAttributeContext attrCtxNewAttr = CdmAttributeContext.CreateChildUnder(projCtx.ProjectionDirective.ResOpt, attrCtxNewAttrParam); ResolvedAttribute newResAttr = null; if (currentPAS.CurrentResolvedAttribute.Target is ResolvedAttributeSet) { // Attribute group // Create a copy of resolved attribute set ResolvedAttributeSet resAttrNewCopy = ((ResolvedAttributeSet)currentPAS.CurrentResolvedAttribute.Target).Copy(); newResAttr = new ResolvedAttribute(projCtx.ProjectionDirective.ResOpt, resAttrNewCopy, currentPAS.CurrentResolvedAttribute.ResolvedName, attrCtxNewAttr); // the resolved attribute group obtained from previous projection operation may have a different set of traits comparing to the resolved attribute target. // We would want to take the set of traits from the resolved attribute. newResAttr.ResolvedTraits = currentPAS.CurrentResolvedAttribute.ResolvedTraits.DeepCopy(); } else if (currentPAS.CurrentResolvedAttribute.Target is CdmAttribute) { // Entity Attribute or Type Attribute newResAttr = CreateNewResolvedAttribute(projCtx, attrCtxNewAttr, currentPAS.CurrentResolvedAttribute, currentPAS.CurrentResolvedAttribute.ResolvedName); } else { Logger.Error(this.Ctx, Tag, nameof(AppendProjectionAttributeState), this.AtCorpusPath, CdmLogCode.ErrProjUnsupportedSource, currentPAS.CurrentResolvedAttribute.Target.ObjectType.ToString(), this.GetName()); // Add the attribute without changes projOutputSet.Add(currentPAS); break; } newResAttr.ResolvedTraits = newResAttr.ResolvedTraits.MergeSet(this.ResolvedNewTraits(projCtx, currentPAS)); this.RemoveTraitsInNewAttribute(projCtx.ProjectionDirective.ResOpt, newResAttr); // Create a projection attribute state for the new attribute with new applied traits by creating a copy of the current state // Copy() sets the current state as the previous state for the new one ProjectionAttributeState newPAS = currentPAS.Copy(); // Update the resolved attribute to be the new attribute we created newPAS.CurrentResolvedAttribute = newResAttr; projOutputSet.Add(newPAS); } else { // Pass through projOutputSet.Add(currentPAS); } } return(projOutputSet); }
/// <inheritdoc /> internal override ProjectionAttributeStateSet AppendProjectionAttributeState( ProjectionContext projCtx, ProjectionAttributeStateSet projOutputSet, CdmAttributeContext attrCtx) { // Create a new attribute context for the operation AttributeContextParameters attrCtxOpRenameAttrsParam = new AttributeContextParameters { under = attrCtx, type = CdmAttributeContextType.OperationRenameAttributes, Name = $"operation/index{Index}/operationRenameAttributes" }; CdmAttributeContext attrCtxOpRenameAttrs = CdmAttributeContext.CreateChildUnder(projCtx.ProjectionDirective.ResOpt, attrCtxOpRenameAttrsParam); // Get the list of attributes that will be renamed List <string> renameAttributes; if (this.ApplyTo != null) { renameAttributes = this.ApplyTo; } else { renameAttributes = new List <string>(); foreach (ProjectionAttributeState currentPAS in projCtx.CurrentAttributeStateSet.States) { renameAttributes.Add(currentPAS.CurrentResolvedAttribute.ResolvedName); } } // Get the top-level attribute names of the attributes to rename // We use the top-level names because the rename list may contain a previous name our current resolved attributes had Dictionary <string, string> topLevelRenameAttributeNames = ProjectionResolutionCommonUtil.GetTopList(projCtx, renameAttributes); string sourceAttributeName = projCtx.ProjectionDirective.OriginalSourceEntityAttributeName; // Initialize a projection attribute context tree builder with the created attribute context for the operation ProjectionAttributeContextTreeBuilder attrCtxTreeBuilder = new ProjectionAttributeContextTreeBuilder(attrCtxOpRenameAttrs); // Iterate through all the projection attribute states generated from the source's resolved attributes // Each projection attribute state contains a resolved attribute that it is corresponding to foreach (ProjectionAttributeState currentPAS in projCtx.CurrentAttributeStateSet.States) { // Check if the current projection attribute state's resolved attribute is in the list of attributes to rename // If this attribute is not in the rename list, then we are including it in the output without changes if (topLevelRenameAttributeNames.ContainsKey(currentPAS.CurrentResolvedAttribute.ResolvedName)) { if (currentPAS.CurrentResolvedAttribute.Target is CdmAttribute) { // The current attribute should be renamed string newAttributeName = GetNewAttributeName(currentPAS, sourceAttributeName); // Create new resolved attribute with the new name, set the new attribute as target ResolvedAttribute resAttrNew = CreateNewResolvedAttribute(projCtx, null, currentPAS.CurrentResolvedAttribute.Target, newAttributeName); // Get the attribute name the way it appears in the applyTo list string applyToName = topLevelRenameAttributeNames[currentPAS.CurrentResolvedAttribute.ResolvedName]; // Create the attribute context parameters and just store it in the builder for now // We will create the attribute contexts at the end attrCtxTreeBuilder.CreateAndStoreAttributeContextParameters(applyToName, currentPAS, resAttrNew, CdmAttributeContextType.AttributeDefinition, currentPAS.CurrentResolvedAttribute.AttCtx, // lineage is the original attribute null); // don't know who will point here yet // Create a projection attribute state for the renamed attribute by creating a copy of the current state // Copy() sets the current state as the previous state for the new one // We only create projection attribute states for attributes that are in the rename list ProjectionAttributeState newPAS = currentPAS.Copy(); // Update the resolved attribute to be the new renamed attribute we created newPAS.CurrentResolvedAttribute = resAttrNew; projOutputSet.Add(newPAS); } else { Logger.Warning(this.Ctx, Tag, nameof(AppendProjectionAttributeState), this.AtCorpusPath, CdmLogCode.WarnProjRenameAttrNotSupported); // Add the attribute without changes projOutputSet.Add(currentPAS); } } else { // Pass through projOutputSet.Add(currentPAS); } } // Create all the attribute contexts and construct the tree attrCtxTreeBuilder.ConstructAttributeContextTree(projCtx); return(projOutputSet); }
/// <inheritdoc /> internal override ProjectionAttributeStateSet AppendProjectionAttributeState( ProjectionContext projCtx, ProjectionAttributeStateSet projOutputSet, CdmAttributeContext attrCtx) { // Create a new attribute context for the operation AttributeContextParameters attrCtxOpExcludeAttrsParam = new AttributeContextParameters { under = attrCtx, type = CdmAttributeContextType.OperationExcludeAttributes, Name = $"operation/index{Index}/operationExcludeAttributes" }; CdmAttributeContext attrCtxOpExcludeAttrs = CdmAttributeContext.CreateChildUnder(projCtx.ProjectionDirective.ResOpt, attrCtxOpExcludeAttrsParam); // Get the top-level attribute names of the attributes to exclude // We use the top-level names because the exclude list may contain a previous name our current resolved attributes had Dictionary <string, string> topLevelExcludeAttributeNames = ProjectionResolutionCommonUtil.GetTopList(projCtx, this.ExcludeAttributes); // Iterate through all the projection attribute states generated from the source's resolved attributes // Each projection attribute state contains a resolved attribute that it is corresponding to foreach (ProjectionAttributeState currentPAS in projCtx.CurrentAttributeStateSet.Values) { // Check if the current projection attribute state's resolved attribute is in the list of attributes to exclude // If this attribute is not in the exclude list, then we are including it in the output if (!topLevelExcludeAttributeNames.ContainsKey(currentPAS.CurrentResolvedAttribute.ResolvedName)) { // Create a new attribute context for the attribute that we are including AttributeContextParameters attrCtxAddedAttrParam = new AttributeContextParameters { under = attrCtx, type = CdmAttributeContextType.AttributeDefinition, Name = currentPAS.CurrentResolvedAttribute.ResolvedName }; CdmAttributeContext attrCtxAddedAttr = CdmAttributeContext.CreateChildUnder(projCtx.ProjectionDirective.ResOpt, attrCtxAddedAttrParam); // Create a projection attribute state for the included attribute // We only create projection attribute states for attributes that are not in the exclude list // Add the current projection attribute state as the previous state of the new projection attribute state ProjectionAttributeState newPAS = new ProjectionAttributeState(projOutputSet.Ctx) { CurrentResolvedAttribute = currentPAS.CurrentResolvedAttribute, PreviousStateList = new List <ProjectionAttributeState> { currentPAS } }; projOutputSet.Add(newPAS); } else { // The current projection attribute state's resolved attribute is in the exclude list // Get the attribute name the way it appears in the exclude list // For our attribute context, we want to use the attribute name the attribute has in the exclude list rather than its current name string excludeAttributeName = null; topLevelExcludeAttributeNames.TryGetValue(currentPAS.CurrentResolvedAttribute.ResolvedName, out excludeAttributeName); // Create a new attribute context for the excluded attribute AttributeContextParameters attrCtxExcludedAttrParam = new AttributeContextParameters { under = attrCtxOpExcludeAttrs, type = CdmAttributeContextType.AttributeDefinition, Name = excludeAttributeName }; CdmAttributeContext attrCtxExcludedAttr = CdmAttributeContext.CreateChildUnder(projCtx.ProjectionDirective.ResOpt, attrCtxExcludedAttrParam); } } return(projOutputSet); }
/// <inheritdoc /> internal override ProjectionAttributeStateSet AppendProjectionAttributeState( ProjectionContext projCtx, ProjectionAttributeStateSet projOutputSet, CdmAttributeContext attrCtx) { // Create a new attribute context for the operation AttributeContextParameters attrCtxOpIncludeAttrsParam = new AttributeContextParameters { under = attrCtx, type = CdmAttributeContextType.OperationIncludeAttributes, Name = $"operation/index{Index}/operationIncludeAttributes" }; CdmAttributeContext attrCtxOpIncludeAttrs = CdmAttributeContext.CreateChildUnder(projCtx.ProjectionDirective.ResOpt, attrCtxOpIncludeAttrsParam); // Get the top-level attribute names for each of the included attributes // Since the include operation allows providing either current state resolved attribute names // or the previous state resolved attribute names, we search for the name in the PAS tree // and fetch the top level resolved attribute names. Dictionary <string, string> topLevelIncludeAttributeNames = ProjectionResolutionCommonUtil.GetTopList(projCtx, this.IncludeAttributes); // Initialize a projection attribute context tree builder with the created attribute context for the operation ProjectionAttributeContextTreeBuilder attrCtxTreeBuilder = new ProjectionAttributeContextTreeBuilder(attrCtxOpIncludeAttrs); // Index that holds the current attribute name as the key and the attribute as value Dictionary <string, ProjectionAttributeState> topLevelIncludeAttribute = new Dictionary <string, ProjectionAttributeState>(); // List of attributes that were not included on the final attribute list List <ProjectionAttributeState> removedAttributes = new List <ProjectionAttributeState>(); // Iterate through all the PAS in the PASSet generated from the projection source's resolved attributes foreach (ProjectionAttributeState currentPAS in projCtx.CurrentAttributeStateSet.States) { // Check if the current PAS's RA is in the list of attributes to include. if (topLevelIncludeAttributeNames.ContainsKey(currentPAS.CurrentResolvedAttribute.ResolvedName)) { topLevelIncludeAttribute.Add(currentPAS.CurrentResolvedAttribute.ResolvedName, currentPAS); } else { removedAttributes.Add(currentPAS); } } // Loop through the list of attributes in the same order that was specified by the user foreach (KeyValuePair <string, string> entry in topLevelIncludeAttributeNames) { // Get the attribute state ProjectionAttributeState currentPAS = topLevelIncludeAttribute[entry.Key]; // Get the attribute name the way it appears in the include list string includeAttributeName = entry.Value; // Create the attribute context parameters and just store it in the builder for now // We will create the attribute contexts at the end attrCtxTreeBuilder.CreateAndStoreAttributeContextParameters(includeAttributeName, currentPAS, currentPAS.CurrentResolvedAttribute, CdmAttributeContextType.AttributeDefinition, currentPAS.CurrentResolvedAttribute.AttCtx, // lineage is the included attribute null); // don't know who will point here yet // Create a projection attribute state for the included attribute by creating a copy of the current state // Copy() sets the current state as the previous state for the new one // We only create projection attribute states for attributes in the include list ProjectionAttributeState newPAS = currentPAS.Copy(); projOutputSet.Add(newPAS); } // Generate attribute context nodes for the attributes that were not included foreach (ProjectionAttributeState currentPAS in removedAttributes) { // Create the attribute context parameters and just store it in the builder for now // We will create the attribute contexts at the end attrCtxTreeBuilder.CreateAndStoreAttributeContextParameters(null, currentPAS, currentPAS.CurrentResolvedAttribute, CdmAttributeContextType.AttributeExcluded, currentPAS.CurrentResolvedAttribute.AttCtx, // lineage is the included attribute null); // don't know who will point here yet } // Create all the attribute contexts and construct the tree attrCtxTreeBuilder.ConstructAttributeContextTree(projCtx); return(projOutputSet); }