/// <summary> /// Builds a new context from the curent builder context for use in processing a flattened reference. /// </summary> /// <param name="builderContext">The builder context.</param> /// <returns>The new builder context for use in processing a flattened reference.</returns> public HqlBuilderContext CreateFlattenedMemberContext(HqlBuilderContext builderContext) { return(_next.CreateFlattenedMemberContext(builderContext)); }
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 resourceMemberToUse = 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)) { // Look for a "descriptor" property if (processorContext.CurrentResourceClass.PropertyByName.TryGetValue( flattenedMemberName, out ResourceProperty descriptorProperty)) { resourceMemberToUse = descriptorProperty; flattenedResource = processorContext.CurrentResourceClass.ResourceModel.GetResourceByFullName( descriptorProperty.DescriptorResource.Entity.FullName); } else { ApplyValidationMessage("resource reference", flattenedMemberName, currentContainingElementName); continue; } } else { resourceMemberToUse = 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; } resourceMemberToUse = 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, resourceMemberToUse); var shouldContinueWithValidation = resourceMemberToUse == 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(resourceMemberToUse, 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)resourceMemberToUse, propertyElements, currentContainingElementName); } _compositeBuilder.ProjectProperties( flattenedPropertyProjections, flattenedBuilderContext, flattenedProcessingContext); // Recursively process flattened resource properties ProcessFlattenedMemberProperties( flattenedProcessingContext, flattenedBuilderContext); } }