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) { // 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); }
/// <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); }
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); }
/// <summary> /// A function to construct projection context and populate the resolved attribute set that ExtractResolvedAttributes method can then extract /// This function is the entry point for projection resolution. /// This function is expected to do the following 3 things: /// - Create an condition expression tree & default if appropriate /// - Create and initialize Projection Context /// - Process operations /// </summary> /// <param name="projDirective"></param> /// <param name="attrCtx"></param> /// <returns></returns> internal ProjectionContext ConstructProjectionContext(ProjectionDirective projDirective, CdmAttributeContext attrCtx) { ProjectionContext projContext = null; if (string.IsNullOrWhiteSpace(this.Condition)) { // if no condition is provided, get default condition and persist this.Condition = ConditionExpression.GetDefaultConditionExpression(this.Operations, this.Owner); } // create an expression tree based on the condition ExpressionTree tree = new ExpressionTree(); this.ConditionExpressionTreeRoot = tree.ConstructExpressionTree(this.Condition); if (this.ConditionExpressionTreeRoot == null) { Logger.Info(nameof(CdmProjection), this.Ctx, $"Optional expression missing. Implicit expression will automatically apply.", nameof(ConstructProjectionContext)); } if (attrCtx != null) { // Add projection to context tree AttributeContextParameters acpProj = new AttributeContextParameters { under = attrCtx, type = CdmAttributeContextType.Projection, Name = this.FetchObjectDefinitionName(), Regarding = projDirective.OwnerRef, IncludeTraits = false }; CdmAttributeContext acProj = CdmAttributeContext.CreateChildUnder(projDirective.ResOpt, acpProj); AttributeContextParameters acpSource = new AttributeContextParameters { under = acProj, type = CdmAttributeContextType.Source, Name = "source", Regarding = null, IncludeTraits = false }; CdmAttributeContext acSource = CdmAttributeContext.CreateChildUnder(projDirective.ResOpt, acpSource); if (this.Source.FetchObjectDefinition <CdmObjectDefinition>(projDirective.ResOpt).ObjectType == CdmObjectType.ProjectionDef) { // A Projection projContext = ((CdmProjection)this.Source.ExplicitReference).ConstructProjectionContext(projDirective, acSource); } else { // An Entity Reference AttributeContextParameters acpSourceProjection = new AttributeContextParameters { under = acSource, type = CdmAttributeContextType.Entity, Name = this.Source.NamedReference ?? this.Source.ExplicitReference.GetName(), Regarding = this.Source, IncludeTraits = false }; ResolvedAttributeSet ras = this.Source.FetchResolvedAttributes(projDirective.ResOpt, acpSourceProjection); // Initialize the projection context CdmCorpusContext ctx = (projDirective.Owner?.Ctx); ProjectionAttributeStateSet pasSet = null; // if polymorphic keep original source as previous state Dictionary <string, List <ProjectionAttributeState> > polySourceSet = null; if (projDirective.IsSourcePolymorphic) { polySourceSet = ProjectionResolutionCommonUtil.GetPolymorphicSourceSet(projDirective, ctx, this.Source, acpSourceProjection); } // now initialize projection attribute state pasSet = ProjectionResolutionCommonUtil.InitializeProjectionAttributeStateSet( projDirective, ctx, ras, isSourcePolymorphic: projDirective.IsSourcePolymorphic, polymorphicSet: polySourceSet); projContext = new ProjectionContext(projDirective, ras.AttributeContext) { CurrentAttributeStateSet = pasSet }; } bool isConditionValid = false; if (this.ConditionExpressionTreeRoot != null) { InputValues input = new InputValues() { noMaxDepth = projDirective.HasNoMaximumDepth, isArray = projDirective.IsArray, referenceOnly = projDirective.IsReferenceOnly, normalized = projDirective.IsNormalized, structured = projDirective.IsStructured, nextDepth = ++projDirective.CurrentDepth, maxDepth = projDirective.MaximumDepth, minCardinality = projDirective.Cardinality?._MinimumNumber, maxCardinality = projDirective.Cardinality?._MaximumNumber }; isConditionValid = ExpressionTree.EvaluateExpressionTree(this.ConditionExpressionTreeRoot, input); } if (isConditionValid && this.Operations != null && this.Operations.Count > 0) { // Just in case new operations were added programmatically, reindex operations for (int i = 0; i < this.Operations.Count; i++) { this.Operations[i].Index = i + 1; } // Operation AttributeContextParameters acpGenAttrSet = new AttributeContextParameters { under = attrCtx, type = CdmAttributeContextType.GeneratedSet, Name = "_generatedAttributeSet" }; CdmAttributeContext acGenAttrSet = CdmAttributeContext.CreateChildUnder(projDirective.ResOpt, acpGenAttrSet); AttributeContextParameters acpGenAttrRound0 = new AttributeContextParameters { under = acGenAttrSet, type = CdmAttributeContextType.GeneratedRound, Name = "_generatedAttributeRound0" }; CdmAttributeContext acGenAttrRound0 = CdmAttributeContext.CreateChildUnder(projDirective.ResOpt, acpGenAttrRound0); // Start with an empty list for each projection ProjectionAttributeStateSet pasOperations = new ProjectionAttributeStateSet(projContext.CurrentAttributeStateSet.Ctx); foreach (CdmOperationBase operation in this.Operations) { // Evaluate projections and apply to empty state ProjectionAttributeStateSet newPasOperations = operation.AppendProjectionAttributeState(projContext, pasOperations, acGenAttrRound0); // If the operations fails or it is not implemented the projection cannot be evaluated so keep previous valid state. if (newPasOperations != null) { pasOperations = newPasOperations; } } // Finally update the current state to the projection context projContext.CurrentAttributeStateSet = pasOperations; } else { // Pass Through - no operations to process } } return(projContext); }
/// <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); }