示例#1
0
        private void ProcessChildren(TBuildResult parentResult,
                                     CompositeDefinitionProcessorContext processorContext,
                                     TBuilderContext parentingBuilderContext)
        {
            var               resourceModel        = processorContext.ResourceModel;
            XElement          currentElt           = processorContext.CurrentElement;
            ResourceClassBase currentResourceClass = processorContext.CurrentResourceClass;

            // Iterate through children (Collection, EmbeddedObject, Resource or Reference)
            var otherChildren = currentElt.Elements(CompositeDefinitionHelper.Collection)
                                .Concat(currentElt.Elements(CompositeDefinitionHelper.EmbeddedObject))
                                .Concat(currentElt.Elements(CompositeDefinitionHelper.LinkedCollection))
                                .Concat(currentElt.Elements(CompositeDefinitionHelper.ReferencedResource));

            int childIndex = 0;

            foreach (var childElt in otherChildren)
            {
                var childProcessorContext = CreateChildProcessorContext(
                    parentResult, processorContext, parentingBuilderContext, childElt, currentResourceClass, resourceModel, childIndex);

                if (childProcessorContext == null)
                {
                    continue;
                }

                var childBuilderContext = _compositeBuilder.CreateChildContext(parentingBuilderContext, childProcessorContext);

                childIndex++;

                ProcessDefinition(parentResult, childBuilderContext, childProcessorContext);
            }
        }
 /// <summary>
 /// Applies properties necessary to support self-referencing association behavior.
 /// </summary>
 /// <param name="selfReferencingAssociations">The relevant self-referencing associations.</param>
 /// <param name="builderContext">The current builder context.</param>
 /// <param name="processorContext">The composite definition processor context.</param>
 /// <remarks>The associations supplied may not be from the current resource class.  In cases where the self-referencing
 /// behavior is obtained through a referenced resource, the associations will be from the referenced resource.</remarks>
 public void ApplySelfReferencingProperties(
     IReadOnlyList <AssociationView> selfReferencingAssociations,
     CompositeResourceModelBuilderContext builderContext,
     CompositeDefinitionProcessorContext processorContext)
 {
     // Nothing to do
 }
 /// <summary>
 /// Applies the provided local identifying properties to the build result using the supplied builder context.
 /// </summary>
 /// <param name="locallyDefinedIdentifyingProperties">The list of local identifying properties to be applied to the build result.</param>
 /// <param name="builderContext">The builder context.</param>
 /// <param name="processorContext">The composite definition processor context.</param>
 public void ApplyLocalIdentifyingProperties(
     IReadOnlyList <EntityProperty> locallyDefinedIdentifyingProperties,
     CompositeResourceModelBuilderContext builderContext,
     CompositeDefinitionProcessorContext processorContext)
 {
     // Nothing to do
 }
 /// <summary>
 /// Builds the artifact for the root resource of the composite definition.
 /// </summary>
 /// <param name="builderContext">The builder context.</param>
 /// <param name="processorContext">The composite definition processor context.</param>
 /// <param name="resource">The resource that is built.</param>
 /// <returns>The build result.</returns>
 public bool TryBuildForRootResource(
     CompositeResourceModelBuilderContext builderContext,
     CompositeDefinitionProcessorContext processorContext,
     out Resource resource)
 {
     resource = builderContext.RootResource;
     return(true);
 }
        /// <summary>
        /// Builds the artifact for the root resource of the composite definition.
        /// </summary>
        /// <param name="parentResult">The parent build result, for compositional behavior (if applicable).</param>
        /// <param name="builderContext">The builder context.</param>
        /// <param name="processorContext">The composite definition processor context.</param>
        /// <returns>The build result.</returns>
        public Resource BuildForChildResource(
            Resource parentResult,
            CompositeResourceModelBuilderContext builderContext,
            CompositeDefinitionProcessorContext processorContext)
        {
            string currentElementName = processorContext.CurrentElement.Name.LocalName;

            switch (currentElementName)
            {
            case Collection:
                AddItem(builderContext.ParentResource.Collections,
                        new Collection(
                            builderContext.ParentResource,
                            builderContext.CurrentResource as ResourceChildItem,
                            processorContext.JoinAssociation,
                            processorContext.MemberDisplayName));

                break;

            case LinkedCollection:

                AddItem(builderContext.ParentResource.Collections,
                        new Collection(
                            builderContext.ParentResource,
                            builderContext.CurrentResource as ResourceChildItem,
                            processorContext.JoinAssociation,
                            processorContext.MemberDisplayName));

                break;

            case ReferencedResource:

                AddItem(builderContext.ParentResource.EmbeddedObjects,
                        new EmbeddedObject(
                            builderContext.ParentResource,
                            builderContext.CurrentResource as ResourceChildItem,
                            processorContext.MemberDisplayName));

                break;

            case EmbeddedObject:

                AddItem(builderContext.ParentResource.EmbeddedObjects,
                        new EmbeddedObject(
                            builderContext.ParentResource,
                            builderContext.CurrentResource as ResourceChildItem,
                            processorContext.MemberDisplayName));

                break;

            default:

                throw new NotSupportedException($"Child element type '{currentElementName}' is not yet supported.");
            }

            // Nothing to compose (results are built in-place using the builder context)
            return(null);
        }
示例#6
0
 private void ApplyLocalIdentifyingProperties(TBuilderContext builderContext, CompositeDefinitionProcessorContext processorContext,
                                              List <EntityProperty> nonIncomingIdentifyingProperties)
 {
     // Apply local identifying properties to the artifact under construction
     _compositeBuilder.ApplyLocalIdentifyingProperties(
         nonIncomingIdentifyingProperties,
         builderContext,
         processorContext);
 }
        /// <summary>
        /// Applies the composite resource's root resource to the build result using the supplied builder context.
        /// </summary>
        /// <param name="processorContext"></param>
        /// <param name="builderContext">The builder context.</param>
        public void ApplyRootResource(CompositeDefinitionProcessorContext processorContext, CompositeResourceModelBuilderContext builderContext)
        {
            string compositeName = processorContext.CurrentElement.Ancestors("Composite")
                                   .First()
                                   .AttributeValue("name");

            string resourceName = CompositeTermInflector.MakeSingular(compositeName);

            builderContext.RootResource    = new Resource(resourceName); //resource.Entity.Name);
            builderContext.CurrentResource = builderContext.RootResource;
        }
 /// <summary>
 /// Creates a new builder context to be used for processing a child element.
 /// </summary>
 /// <param name="parentingBuilderContext">The parent context to be used to derive the new child context.</param>
 /// <param name="childProcessorContext"></param>
 /// <returns>The new builder context.</returns>
 public CompositeResourceModelBuilderContext CreateChildContext(
     CompositeResourceModelBuilderContext parentingBuilderContext,
     CompositeDefinitionProcessorContext childProcessorContext)
 {
     return(new CompositeResourceModelBuilderContext
     {
         RootResource = parentingBuilderContext.RootResource, ParentResource = parentingBuilderContext.CurrentResource,
         CurrentResource = new ResourceChildItem(
             childProcessorContext.CurrentResourceClass.Name,
             parentingBuilderContext.CurrentResource)
     });
 }
        public static IReadOnlyDictionary <string, ResourceProperty> ValidPropertiesByName(
            CompositeDefinitionProcessorContext processorContext,
            IReadOnlyDictionary <string, ResourceProperty> propertiesByName)
        {
            Preconditions.ThrowIfNull(processorContext, nameof(processorContext));
            Preconditions.ThrowIfNull(propertiesByName, nameof(propertiesByName));

            return(processorContext.ShouldIncludeResourceSubtype()
                ? propertiesByName
                   .Where(p => p.Value.IsIdentifying)
                   .ToDictionary(k => k.Key, v => v.Value)
                : propertiesByName);
        }
示例#10
0
        private void ApplyReferenceHierarchy(TBuilderContext builderContext, CompositeDefinitionProcessorContext processorContext)
        {
            if (processorContext.ShouldUseReferenceHierarchy())
            {
                string referenceName = processorContext.AttributeValue(CompositeDefinitionHelper.HierarchicalReferenceName);

                var referencedResourceClass = processorContext.CurrentResourceClass.ReferenceByName[referenceName]
                                              .ReferencedResource;

                _compositeBuilder.ApplySelfReferencingProperties(
                    referencedResourceClass.Entity.SelfReferencingAssociations,
                    builderContext,
                    processorContext);
            }
        }
示例#11
0
        private List <CompositePropertyProjection> GetPropertyProjectionsForNonAggregateRoot(
            CompositeDefinitionProcessorContext processorContext,
            EmbeddedObject currentMember,
            IEnumerable <XElement> propertyElements,
            string containingElementName)
        {
            var selectedElements      = CompositeDefinitionHelper.CreateSelectedElements(propertyElements);
            var validPropertiesByName = CompositeDefinitionHelper.ValidPropertiesByName(processorContext, currentMember.ObjectType.PropertyByName);
            var validProperties       = CompositeDefinitionHelper.GetValidProperties(selectedElements, validPropertiesByName);

            ValidateSelectedElements(selectedElements, validProperties, containingElementName, processorContext.ShouldIncludeResourceSubtype());

            return(validProperties
                   .Select(pn => new CompositePropertyProjection(currentMember.ObjectType.AllPropertyByName[pn.Name], pn.DisplayName))
                   .ToList());
        }
示例#12
0
        public TBuildResult Process(
            XElement compositeDefinition,
            IResourceModel resourceModel,
            TBuilderContext builderContext)
        {
            var currentElt = compositeDefinition.Element(CompositeDefinitionHelper.BaseResource);

            if (currentElt == null)
            {
                throw new Exception("Unable to find the main 'Resource' element of the composite definition.");
            }

            var resourceLogicalName = currentElt.AttributeValue(CompositeDefinitionHelper.LogicalSchema) ?? EdFiConventions.LogicalName;

            var resourcePhysicalName = resourceModel.SchemaNameMapProvider
                                       .GetSchemaMapByLogicalName(resourceLogicalName)
                                       .PhysicalName;

            // Composites does not support extensions
            var currentModel =
                resourceModel.GetResourceByFullName(
                    new FullName(resourcePhysicalName, currentElt.AttributeValue(CompositeDefinitionHelper.Name)));

            var processorContext = new CompositeDefinitionProcessorContext(
                compositeDefinition,
                resourceModel,
                currentElt,
                currentModel,
                null,
                null,
                null,
                0,
                null);

            return(ProcessDefinition(default(TBuildResult), builderContext, processorContext));
        }
示例#13
0
        private List <CompositePropertyProjection> GetPropertyProjections(
            CompositeDefinitionProcessorContext processorContext,
            IEnumerable <XElement> propertyElements)
        {
            var selectedElements = CompositeDefinitionHelper.CreateSelectedElements(propertyElements);

            // only allow identifying properties for pass through resources.
            var validPropertiesByName = CompositeDefinitionHelper.ValidPropertiesByName(
                processorContext, processorContext.CurrentResourceClass.AllPropertyByName);

            var validProperties = CompositeDefinitionHelper.GetValidProperties(selectedElements, validPropertiesByName);

            ValidateSelectedElements(
                selectedElements, validProperties,
                processorContext.CurrentElement.AttributeValue(CompositeDefinitionHelper.Name),
                processorContext.ShouldIncludeResourceSubtype());

            return(validProperties.Select(
                       pn =>
                       new CompositePropertyProjection(
                           processorContext.CurrentResourceClass.AllPropertyByName[pn.Name],
                           pn.DisplayName))
                   .ToList());
        }
示例#14
0
        private TBuildResult ProcessDefinition(
            TBuildResult parentResult,
            TBuilderContext builderContext,
            CompositeDefinitionProcessorContext processorContext)
        {
            // Apply authorization for aggregate roots here
            if (processorContext.CurrentResourceClass.Entity.IsAggregateRoot)
            {
                // Provide opportunity to perform processing related to navigating into another resource (i.e. authorization)
                if (!_compositeBuilder.TryIncludeResource(processorContext, builderContext))
                {
                    return(default(TBuildResult));
                }
            }

            bool isMainQuery = processorContext.IsBaseResource();

            if (isMainQuery)
            {
                _compositeBuilder.ApplyRootResource(processorContext, builderContext);
            }
            else
            {
                _compositeBuilder.ApplyChildResource(builderContext, processorContext);
            }

            var nonIncomingIdentifyingProperties = processorContext.NonIncomingIdentifyingProperties();

            ApplyLocalIdentifyingProperties(builderContext, processorContext, nonIncomingIdentifyingProperties);

            ApplySelfReferencingAssociations(builderContext, processorContext);

            ApplyReferenceHierarchy(builderContext, processorContext);

            // Capture current applicable builder state so it can be modified further at this level without changes affecting children
            _compositeBuilder.SnapshotParentingContext(builderContext);

            // Select projected properties
            var propertyProjections = GetPropertyProjections(processorContext, processorContext.PropertyElements());

            // Project the properties into the artifact under construction
            _compositeBuilder.ProjectProperties(propertyProjections, builderContext, processorContext);

            // Process flattened References
            ProcessFlattenedMemberProperties(processorContext, builderContext);

            TBuildResult thisBuildResult;

            if (isMainQuery)
            {
                // Short circuit the rest of the processing if the root result is null
                if (!_compositeBuilder.TryBuildForRootResource(builderContext, processorContext, out thisBuildResult))
                {
                    return(default(TBuildResult));
                }
            }
            else
            {
                thisBuildResult = _compositeBuilder.BuildForChildResource(
                    parentResult,
                    builderContext,
                    processorContext);
            }

            var childBuilderContext = _compositeBuilder.CreateParentingContext(builderContext);

            ProcessChildren(thisBuildResult, processorContext, childBuilderContext);

            if (_performValidation && _validationErrors.Any())
            {
                throw new Exception(string.Join(Environment.NewLine, _validationErrors.ToArray()));
            }

            return(thisBuildResult);
        }
示例#15
0
        private void ProcessFlattenedMemberProperties(
            CompositeDefinitionProcessorContext processorContext,
            TBuilderContext builderContext)
        {
            string currentContainingElementName = processorContext.CurrentElement.AttributeValue(CompositeDefinitionHelper.Name);

            var flattenedMemberElements = processorContext.CurrentElement
                                          .Elements(CompositeDefinitionHelper.ReferencedResource)
                                          .Where(CompositeDefinitionHelper.ShouldFlatten)
                                          .ToList();

            flattenedMemberElements.AddRange(
                processorContext.CurrentElement
                .Elements(CompositeDefinitionHelper.EmbeddedObject)
                .Where(CompositeDefinitionHelper.ShouldFlatten));

            foreach (var flattenedMemberElt in flattenedMemberElements)
            {
                string flattenedMemberName = flattenedMemberElt.AttributeValue(CompositeDefinitionHelper.Name);

                ResourceMemberBase resourceToUse     = null;
                Resource           flattenedResource = null;

                bool memberIsReference      = flattenedMemberElt.Name.LocalName == CompositeDefinitionHelper.ReferencedResource;
                bool memberIsEmbeddedObject = flattenedMemberElt.Name.LocalName == CompositeDefinitionHelper.EmbeddedObject;

                if (memberIsReference)
                {
                    if (!processorContext.CurrentResourceClass.ReferenceByName.TryGetValue(
                            flattenedMemberName, out Reference resourceToUseAsReference))
                    {
                        ApplyValidationMessage("resource reference", flattenedMemberName, currentContainingElementName);
                        continue;
                    }

                    resourceToUse = resourceToUseAsReference;

                    flattenedResource =
                        processorContext.CurrentResourceClass.ResourceModel.GetResourceByFullName(
                            resourceToUseAsReference.ReferencedResource.Entity.FullName);
                }
                else if (memberIsEmbeddedObject)
                {
                    if (!processorContext.CurrentResourceClass.EmbeddedObjectByName.TryGetValue(
                            flattenedMemberName, out EmbeddedObject resourceAsEmbeddedObject))
                    {
                        ApplyValidationMessage("embedded object", flattenedMemberName, currentContainingElementName);
                        continue;
                    }

                    resourceToUse = resourceAsEmbeddedObject;

                    flattenedResource =
                        processorContext.CurrentResourceClass.ResourceModel.GetResourceByFullName(resourceAsEmbeddedObject.Parent.Entity.FullName);
                }
                else
                {
                    // Defensive programming, but also throw a helpful message in the event it does ever happen
                    throw new NotSupportedException($"Flattened elements of type '{flattenedMemberElt.Name.LocalName}' are not yet supported.");
                }

                var flattenedBuilderContext = _compositeBuilder.CreateFlattenedMemberContext(builderContext);

                var flattenedProcessingContext = new CompositeDefinitionProcessorContext(
                    processorContext.CompositeDefinitionElement,
                    processorContext.ResourceModel,
                    flattenedMemberElt,
                    flattenedResource,
                    null,
                    null,
                    null,
                    0,
                    resourceToUse);

                var shouldContinueWithValidation = resourceToUse == null && _performValidation;

                if (flattenedResource.Entity.IsAggregateRoot)
                {
                    // Provide opportunity to perform processing related to navigating into another resource (i.e. authorization)
                    if (!_compositeBuilder.TryIncludeResource(flattenedProcessingContext, flattenedBuilderContext))
                    {
                        continue;
                    }
                }

                if (shouldContinueWithValidation)
                {
                    continue;
                }

                _compositeBuilder.ApplyFlattenedMember(resourceToUse, flattenedBuilderContext);

                // TODO: Consider refining what is passed into Resource model classes rather than XElements
                var propertyElements = flattenedMemberElt
                                       .Elements(CompositeDefinitionHelper.Property)
                                       .ToList();

                List <CompositePropertyProjection> flattenedPropertyProjections = new List <CompositePropertyProjection>();

                if (memberIsReference)
                {
                    flattenedPropertyProjections = GetPropertyProjections(
                        flattenedProcessingContext,
                        propertyElements);
                }
                else if (memberIsEmbeddedObject)
                {
                    flattenedPropertyProjections = GetPropertyProjectionsForNonAggregateRoot(
                        processorContext,
                        (EmbeddedObject)resourceToUse,
                        propertyElements,
                        currentContainingElementName);
                }

                _compositeBuilder.ProjectProperties(flattenedPropertyProjections, flattenedBuilderContext, flattenedProcessingContext);

                // Recursively process flattened resource properties
                ProcessFlattenedMemberProperties(
                    flattenedProcessingContext,
                    flattenedBuilderContext);
            }
        }
示例#16
0
        private CompositeDefinitionProcessorContext CreateChildProcessorContext(TBuildResult parentResult,
                                                                                CompositeDefinitionProcessorContext processorContext,
                                                                                TBuilderContext parentingBuilderContext,
                                                                                XElement childElement,
                                                                                ResourceClassBase currentResourceClass,
                                                                                IResourceModel resourceModel, int childIndex)
        {
            ResourceClassBase  childModel;
            AssociationView    association;
            ResourceMemberBase resourceMember;

            string childMemberName        = childElement.AttributeValue(CompositeDefinitionHelper.Name);
            string childMemberDisplayName = childElement.AttributeValue(CompositeDefinitionHelper.DisplayName);
            string currentElementName     = processorContext.CurrentElement.AttributeValue(CompositeDefinitionHelper.Name);

            string resourceMemberName    = string.Empty;
            string childEntityMemberName = string.Empty;

            switch (childElement.Name.LocalName)
            {
            case CompositeDefinitionHelper.Collection:

                if (!currentResourceClass.CollectionByName.TryGetValue(childMemberName, out Collection collection))
                {
                    ApplyValidationMessage("collection", childMemberName, currentElementName);
                    return(null);
                }

                _logger.Debug($"Current element '{currentElementName}' is a collection named '{childMemberName}'.");

                childModel            = collection.ItemType;
                childEntityMemberName = childMemberName;
                association           = collection.Association;
                resourceMember        = collection;
                resourceMemberName    = collection.PropertyName;

                break;

            case CompositeDefinitionHelper.LinkedCollection:

                var resource = currentResourceClass as Resource;

                if (resource == null)
                {
                    _logger.Debug($"Current resource class '{currentResourceClass.Name} is not an aggregate root.");
                    return(null);
                }

                if (!resource.LinkedResourceCollectionByName.TryGetValue(childMemberName, out LinkedCollection linkedCollection))
                {
                    ApplyValidationMessage("linked collection", childMemberName, currentElementName);
                    return(null);
                }

                _logger.Debug(
                    $"Current element '{currentElementName} is a linked collection named '{childMemberName}' for resource '{currentResourceClass.Name}'.");

                childModel            = linkedCollection.Resource;
                childEntityMemberName = childMemberName;
                association           = linkedCollection.Association;
                resourceMember        = linkedCollection;
                resourceMemberName    = linkedCollection.PropertyName;

                break;

            case CompositeDefinitionHelper.EmbeddedObject:

                if (!currentResourceClass.EmbeddedObjectByName.TryGetValue(childMemberName, out EmbeddedObject embeddedObject))
                {
                    ApplyValidationMessage("embedded object", childMemberName, currentElementName);

                    return(null);
                }

                _logger.Debug($"Current element '{currentElementName}' is an embedded object named '{childMemberName}'.");

                childModel            = embeddedObject.ObjectType;
                childEntityMemberName = embeddedObject.Association.Name;
                association           = embeddedObject.Association;
                resourceMember        = embeddedObject;
                resourceMemberName    = embeddedObject.PropertyName;

                if (CompositeDefinitionHelper.ShouldFlatten(childElement))
                {
                    _logger.Debug($"Flattening embedded object {childModel.Name}");

                    _compositeBuilder.ApplyFlattenedMember(embeddedObject, parentingBuilderContext);

                    var childBuilderContextForObject = _compositeBuilder.CreateFlattenedReferenceChildContext(parentingBuilderContext);

                    var childProcessorContextForObject = new CompositeDefinitionProcessorContext(
                        processorContext.CompositeDefinitionElement,
                        resourceModel,
                        childElement,
                        childModel,
                        association,
                        childEntityMemberName,
                        resourceMemberName,
                        childIndex,
                        resourceMember);

                    ProcessChildren(parentResult, childProcessorContextForObject, childBuilderContextForObject);

                    return(null);
                }

                break;

            case CompositeDefinitionHelper.ReferencedResource:

                if (!currentResourceClass.ReferenceByName.TryGetValue(childMemberName, out Reference reference))
                {
                    ApplyValidationMessage("referenced resource", childMemberName, currentElementName);

                    return(null);
                }

                _logger.Debug($"Current element '{currentElementName}' is an referenced resourced named '{childMemberName}'.");

                childModel            = reference.ReferencedResource;
                childEntityMemberName = reference.Association.Name;
                association           = reference.Association;
                resourceMember        = reference;
                resourceMemberName    = reference.PropertyName;

                // If reference is flattened, process recursively without adding another query at this level.
                if (CompositeDefinitionHelper.ShouldFlatten(childElement))
                {
                    _logger.Debug($"Flattening referenced resource {childModel.Name}");

                    _compositeBuilder.ApplyFlattenedMember(reference, parentingBuilderContext);

                    var childBuilderContextForReference = _compositeBuilder.CreateFlattenedReferenceChildContext(parentingBuilderContext);

                    var childProcessorContextForReference = new CompositeDefinitionProcessorContext(
                        processorContext.CompositeDefinitionElement,
                        resourceModel,
                        childElement,
                        childModel,
                        association,
                        childEntityMemberName,
                        resourceMemberName,
                        childIndex,
                        resourceMember);

                    if (childModel.Entity.IsAggregateRoot)
                    {
                        // Provide opportunity to perform processing related to navigating into another resource (i.e. authorization)
                        if (!_compositeBuilder.TryIncludeResource(childProcessorContextForReference, childBuilderContextForReference))
                        {
                            return(null);
                        }
                    }

                    ProcessChildren(parentResult, childProcessorContextForReference, childBuilderContextForReference);

                    return(null);
                }

                break;

            default:

                throw new NotSupportedException($"Element '{childElement.Name.LocalName}' is not supported.");
            }

            return(new CompositeDefinitionProcessorContext(
                       processorContext.CompositeDefinitionElement,
                       resourceModel,
                       childElement,
                       childModel,
                       association,
                       childEntityMemberName,
                       childMemberDisplayName ?? resourceMemberName,
                       childIndex,
                       resourceMember));
        }
 /// <summary>
 /// Applies processing related to the usage/entry to another top-level resource (e.g. applying authorization concerns).
 /// </summary>
 /// <param name="processorContext">The composite definition processor context.</param>
 /// <param name="builderContext">The current builder context.</param>
 /// <returns><b>true</b> if the resource can be processed; otherwise <b>false</b>.</returns>
 public bool TryIncludeResource(CompositeDefinitionProcessorContext processorContext, CompositeResourceModelBuilderContext builderContext)
 {
     // No reason not to include the resource in this usage scenario
     return(true);
 }
 /// <summary>
 /// Applies the composite resource's child resource to the build result using the supplied builder context.
 /// </summary>
 /// <param name="builderContext">The builder context.</param>
 /// <param name="processorContext">The composite definition processor context.</param>
 public void ApplyChildResource(
     CompositeResourceModelBuilderContext builderContext,
     CompositeDefinitionProcessorContext processorContext)
 {
     // Nothing to apply (we only need to actually build the model)
 }
示例#19
0
 private void ApplySelfReferencingAssociations(TBuilderContext builderContext, CompositeDefinitionProcessorContext processorContext)
 {
     if (processorContext.CurrentResourceClass.Entity.HasSelfReferencingAssociations &&
         processorContext.ShouldUseHierarchy())
     {
         _compositeBuilder.ApplySelfReferencingProperties(
             processorContext.CurrentResourceClass.Entity.SelfReferencingAssociations,
             builderContext,
             processorContext);
     }
 }
        /// <summary>
        /// Apply the provided property projections onto the build result with the provided builder and composite
        /// definition processor contexts.
        /// </summary>
        /// <param name="propertyProjections">A list of property projections to be applied to the build result.</param>
        /// <param name="builderContext">The builder context.</param>
        /// <param name="processorContext">The composite definition processor context.</param>
        public void ProjectProperties(
            IReadOnlyList <CompositePropertyProjection> propertyProjections,
            CompositeResourceModelBuilderContext builderContext,
            CompositeDefinitionProcessorContext processorContext)
        {
            // Local reused functional predicate
            var isIdProperty = new Func <CompositePropertyProjection, bool>(
                p =>
                p.ResourceProperty.PropertyName.EqualsIgnoreCase("Id"));

            // Ensure Id property appears first
            var orderedPropertyProjections =
                propertyProjections.Where(isIdProperty)
                .Concat(propertyProjections.Where(p => !isIdProperty(p)));

            if (processorContext.ShouldIncludeResourceSubtype())
            {
                Logger.Debug($"Adding the resource type the property collection");

                AddItem(
                    builderContext.CurrentResource.Properties,
                    new ResourceProperty(
                        builderContext.CurrentResource,
                        processorContext.CurrentResourceClass.Name.ToCamelCase() + "Type",
                        new PropertyType(DbType.AnsiString, 128, 0, 0, true),
                        new PropertyCharacteristics(
                            false,
                            false,
                            false,
                            true, // All projected properties are "local" properties on the new object
                            false,
                            null),
                        null));
            }

            foreach (var property in orderedPropertyProjections)
            {
                Logger.Debug($"Projecting property {property.ResourceProperty.PropertyName}.");
                var entityProperty = property.ResourceProperty.EntityProperty;

                if (!builderContext.CurrentResource.IsAbstract() ||
                    builderContext.CurrentResource.IsAbstract() &&
                    entityProperty.IsIdentifying &&
                    processorContext.ShouldIncludeResourceSubtype())
                {
                    Logger.Debug($"Adding property {property.ResourceProperty.PropertyName} to the builder context.");

                    AddItem(
                        builderContext.CurrentResource.Properties,
                        new ResourceProperty(
                            builderContext.CurrentResource,
                            property.DisplayName ?? property.ResourceProperty.PropertyName,
                            property.ResourceProperty.PropertyType,
                            new PropertyCharacteristics(
                                entityProperty.IsLookup,
                                entityProperty.IsDirectLookup,
                                entityProperty.IsIdentifying,
                                true, // All projected properties are "local" properties on the new object
                                entityProperty.IsServerAssigned,
                                entityProperty.LookupEntity == null
                                    ? null as FullName?
                                    : entityProperty.LookupEntity.FullName),
                            property.ResourceProperty.Description));
                }
                else
                {
                    Logger.Debug($"Stripping property {property.ResourceProperty.PropertyName} from the builder context.");
                }
            }
        }