Example #1
0
        /// <summary>
        /// Constructor which creates an empty root.
        /// </summary>
        /// <param name="epmTargetTree">Target xml tree</param>
        internal EpmSourceTree(EpmTargetTree epmTargetTree)
        {
            DebugUtils.CheckNoExternalCallers();

            this.root          = new EpmSourcePathSegment();
            this.epmTargetTree = epmTargetTree;
        }
Example #2
0
 private void WriteEntryEpm(XmlWriter writer, EpmTargetTree epmTargetTree, EntryPropertiesValueCache epmValueCache, IEdmEntityTypeReference entityType)
 {
     EpmTargetPathSegment nonSyndicationRoot = epmTargetTree.NonSyndicationRoot;
     if (nonSyndicationRoot.SubSegments.Count != 0)
     {
         foreach (EpmTargetPathSegment segment2 in nonSyndicationRoot.SubSegments)
         {
             string alreadyDeclaredPrefix = null;
             this.WriteElementEpm(writer, segment2, epmValueCache, entityType, ref alreadyDeclaredPrefix);
         }
     }
 }
Example #3
0
        /// <summary>
        /// Writes the custom mapped EPM properties to an XML writer which is expected to be positioned such to write
        /// a child element of the entry element.
        /// </summary>
        /// <param name="writer">The XmlWriter to write to.</param>
        /// <param name="epmTargetTree">The EPM target tree to use.</param>
        /// <param name="epmValueCache">The entry properties value cache to use to access the properties.</param>
        /// <param name="entityType">The type of the entry.</param>
        /// <param name="atomOutputContext">The output context currently in use.</param>
        internal static void WriteEntryEpm(
            XmlWriter writer,
            EpmTargetTree epmTargetTree,
            EntryPropertiesValueCache epmValueCache,
            IEdmEntityTypeReference entityType,
            ODataAtomOutputContext atomOutputContext)
        {
            DebugUtils.CheckNoExternalCallers();

            EpmCustomWriter epmWriter = new EpmCustomWriter(atomOutputContext);
            epmWriter.WriteEntryEpm(writer, epmTargetTree, epmValueCache, entityType);
        }
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="mappings">The EPM mappings to create the cache for.</param>
        /// <param name="model">The EDM model.</param>
        /// <param name="totalMappingCount">The total number of entity property mappings
        /// for the entity type that this cache is created for (on the type itself and all its base types).</param>
        internal ODataEntityPropertyMappingCache(ODataEntityPropertyMappingCollection mappings, IEdmModel model, int totalMappingCount)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(model.IsUserModel(), "model.IsUserModel()");

            this.mappings          = mappings;
            this.model             = model;
            this.totalMappingCount = totalMappingCount;

            // Note that we new up everything here eagerly because we will only create the EPM annotation for types
            // for which we know for sure that they have EPM and thus we will need all of these anyway.
            this.mappingsForInheritedProperties = new List <EntityPropertyMappingAttribute>();
            this.mappingsForDeclaredProperties  = mappings == null
                ? new List <EntityPropertyMappingAttribute>()
                : new List <EntityPropertyMappingAttribute>(mappings);
            this.epmTargetTree = new EpmTargetTree();
            this.epmSourceTree = new EpmSourceTree(this.epmTargetTree);
        }
Example #5
0
        internal void Add(EntityPropertyMappingInfo epmInfo)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(epmInfo != null, "epmInfo != null");

            string targetPath      = epmInfo.Attribute.TargetPath;
            string namespaceUri    = epmInfo.Attribute.TargetNamespaceUri;
            string namespacePrefix = epmInfo.Attribute.TargetNamespacePrefix;

            EpmTargetPathSegment         currentSegment    = epmInfo.IsSyndicationMapping ? this.SyndicationRoot : this.NonSyndicationRoot;
            IList <EpmTargetPathSegment> activeSubSegments = currentSegment.SubSegments;

            Debug.Assert(!string.IsNullOrEmpty(targetPath), "Must have been validated during EntityPropertyMappingAttribute construction");
            string[] targetSegments = targetPath.Split('/');

            EpmTargetPathSegment foundSegment = null;

            for (int i = 0; i < targetSegments.Length; i++)
            {
                string targetSegment = targetSegments[i];

                if (targetSegment.Length == 0)
                {
                    throw new ODataException(Strings.EpmTargetTree_InvalidTargetPath_EmptySegment(targetPath));
                }

                if (targetSegment[0] == '@' && i != targetSegments.Length - 1)
                {
                    throw new ODataException(Strings.EpmTargetTree_AttributeInMiddle(targetSegment));
                }

                foundSegment = activeSubSegments.SingleOrDefault(
                    segment => segment.SegmentName == targetSegment &&
                    (epmInfo.IsSyndicationMapping || segment.SegmentNamespaceUri == namespaceUri));

                if (foundSegment != null)
                {
                    currentSegment = foundSegment;
                }
                else
                {
                    currentSegment = new EpmTargetPathSegment(targetSegment, namespaceUri, namespacePrefix, currentSegment);

                    if (targetSegment[0] == '@')
                    {
                        activeSubSegments.Insert(0, currentSegment);
                    }
                    else
                    {
                        activeSubSegments.Add(currentSegment);
                    }
                }

                activeSubSegments = currentSegment.SubSegments;
            }

            if (currentSegment.EpmInfo != null)
            {
                // Two EpmAttributes with same TargetName in the inheritance hierarchy
                throw new ODataException(Strings.EpmTargetTree_DuplicateEpmAttributesWithSameTargetName(currentSegment.EpmInfo.DefiningType.ODataFullName(), EpmTargetTree.GetPropertyNameFromEpmInfo(currentSegment.EpmInfo), currentSegment.EpmInfo.Attribute.SourcePath, epmInfo.Attribute.SourcePath));
            }

            // Increment the number of properties for which KeepInContent is false
            if (!epmInfo.Attribute.KeepInContent)
            {
                this.countOfNonContentV2Mappings++;
            }

            currentSegment.EpmInfo = epmInfo;

            // Mixed content is dis-allowed.
            List <EntityPropertyMappingAttribute> conflictingAttributes = new List <EntityPropertyMappingAttribute>(2);

            if (EpmTargetTree.HasMixedContent(this.NonSyndicationRoot, conflictingAttributes))
            {
                Debug.Assert(conflictingAttributes.Count == 2, "Expected to find exactly two conflicting attributes.");
                throw new ODataException(Strings.EpmTargetTree_InvalidTargetPath_MixedContent(conflictingAttributes[0].TargetPath, conflictingAttributes[1].TargetPath));
            }
        }
Example #6
0
 internal static void WriteEntryEpm(XmlWriter writer, EpmTargetTree epmTargetTree, EntryPropertiesValueCache epmValueCache, IEdmEntityTypeReference entityType, ODataAtomOutputContext atomOutputContext)
 {
     new EpmCustomWriter(atomOutputContext).WriteEntryEpm(writer, epmTargetTree, epmValueCache, entityType);
 }
Example #7
0
 internal EpmSourceTree(EpmTargetTree epmTargetTree)
 {
     this.epmTargetTree = epmTargetTree;
 }
Example #8
0
 internal EpmSourceTree(EpmTargetTree epmTargetTree)
 {
     this.epmTargetTree = epmTargetTree;
 }
Example #9
0
        /// <summary>
        /// Writes the custom mapped EPM properties to an XML writer which is expected to be positioned such to write
        /// a child element of the entry element.
        /// </summary>
        /// <param name="writer">The XmlWriter to write to.</param>
        /// <param name="epmTargetTree">The EPM target tree to use.</param>
        /// <param name="epmValueCache">The entry properties value cache to use to access the properties.</param>
        /// <param name="entityType">The type of the entry.</param>
        private void WriteEntryEpm(
            XmlWriter writer,
            EpmTargetTree epmTargetTree,
            EntryPropertiesValueCache epmValueCache,
            IEdmEntityTypeReference entityType)
        {
            Debug.Assert(writer != null, "writer != null");
            Debug.Assert(epmTargetTree != null, "epmTargetTree != null");
            Debug.Assert(epmValueCache != null, "epmValueCache != null");
            Debug.Assert(entityType != null, "For any EPM to exist the metadata must be available.");

            // If there are no custom mappings, just return null.
            EpmTargetPathSegment customRootSegment = epmTargetTree.NonSyndicationRoot;
            Debug.Assert(customRootSegment != null, "EPM Target tree must always have non-syndication root.");
            if (customRootSegment.SubSegments.Count == 0)
            {
                return;
            }

            foreach (EpmTargetPathSegment targetSegment in customRootSegment.SubSegments)
            {
                Debug.Assert(!targetSegment.IsAttribute, "Target segments under the custom root must be for elements only.");

                string alreadyDeclaredPrefix = null;
                this.WriteElementEpm(writer, targetSegment, epmValueCache, entityType, ref alreadyDeclaredPrefix);
            }
        }