/// <summary> /// Initializes the EPM annotation with EPM information from the specified resource type. /// </summary> /// <param name="definingResourceType">Resource type to use the EPM infromation from.</param> /// <param name="affectedResourceType">Resource type for this the EPM information is being built.</param> private void BuildEpmForType(ResourceType definingResourceType, ResourceType affectedResourceType) { Debug.Assert(definingResourceType != null, "definingResourceType != null"); Debug.Assert(affectedResourceType != null, "affectedResourceType != null"); if (definingResourceType.BaseType != null) { this.BuildEpmForType(definingResourceType.BaseType, affectedResourceType); } EpmResourceTypeAnnotation epm = definingResourceType.Epm(); if (epm != null) { foreach (EntityPropertyMappingAttribute epmAttribute in epm.AllEpmAttributes.ToList()) { this.epmSourceTree.Add(new EntityPropertyMappingInfo(epmAttribute, definingResourceType, affectedResourceType)); if (definingResourceType == affectedResourceType) { if (!PropertyExistsOnType(affectedResourceType, epmAttribute)) { this.InheritedEpmAttributes.Add(epmAttribute); this.OwnEpmAttributes.Remove(epmAttribute); } else { Debug.Assert( this.OwnEpmAttributes.SingleOrDefault(attr => Object.ReferenceEquals(epmAttribute, attr)) != null, "Own epmInfo should already have the given instance"); } } } } }
/// <summary> /// Initializes the EPM internal information for the specified resource type and all its base types. /// </summary> /// <param name="resourceType">The resource type to build the EPM information for.</param> /// <remarks>If the type in question has no EPM attributes anywhere in its hierarchy this method will do nothing.</remarks> internal static void BuildEpm(ResourceType resourceType) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(resourceType != null, "resourceType != null"); // Walk the base types and determine if there's EPM anywhere in there. bool hasEpm = false; ResourceType resourceTypeToTest = resourceType; while (resourceTypeToTest != null) { if (resourceTypeToTest.Epm() != null) { hasEpm = true; break; } resourceTypeToTest = resourceTypeToTest.BaseType; } // If there is build the EPM information for this type and add it as annotation. if (hasEpm) { EpmResourceTypeAnnotation epm = resourceType.Epm(); if (epm == null) { epm = new EpmResourceTypeAnnotation(); // resourceType.SetAnnotation(epm); } epm.BuildEpmForType(resourceType, resourceType); } }
/// <summary> /// Check whether the EPM on the specified resource type is supported in the specified version. /// </summary> /// <param name="version">The version to check.</param> /// <param name="resourceType">The entity resoure type to check.</param> internal static void CheckEntityPropertyMapping(ODataVersion version, ResourceType resourceType) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(resourceType != null, "resourceType != null"); EpmResourceTypeAnnotation epmAnnotation = resourceType.Epm(); if (epmAnnotation != null) { Debug.Assert(epmAnnotation.EpmTargetTree != null, "If the EPM annotation is present the EPM tree must already be initialized."); if (version < epmAnnotation.EpmTargetTree.MinimumODataProtocolVersion) { throw new ODataException( Strings.ODataVersionChecker_EpmVersionNotSupported( resourceType.FullName, epmAnnotation.EpmTargetTree.MinimumODataProtocolVersion.VersionString(), version.VersionString())); } } }
/// <summary> /// Finish writing an entry. /// </summary> /// <param name="entry">The entry to write.</param> protected override void EndEntry(ODataEntry entry) { Debug.Assert(entry != null, "entry != null"); string typeName = entry.TypeName; ResourceType entryType = ValidationUtils.ValidateTypeName(this.MetadataProvider, typeName, ResourceTypeKind.EntityType, false); // Initialize the property value cache and cache the entry properties. EntryPropertiesValueCache propertyValueCache = new EntryPropertiesValueCache(entry); EpmResourceTypeAnnotation epmResourceTypeAnnotation = null; if (entryType != null) { Debug.Assert(entryType.IsReadOnly, "The resource must be read-only to be applied to an entry."); entryType.EnsureEpmAvailability(); epmResourceTypeAnnotation = entryType.Epm(); } // <atom:id>idValue</atom:id> // NOTE: do not generate a relative Uri for the ID; it is independent of xml:base ODataAtomWriterUtils.WriteElementWithTextContent( this.writer, AtomConstants.AtomNamespacePrefix, AtomConstants.AtomIdElementName, AtomConstants.AtomNamespace, entry.Id); // <category term="type" scheme="odatascheme"/> // If no type information is provided, don't include the category element for type at all // NOTE: the validation of the type name happened at the beginning of this method. if (typeName != null) { ODataAtomWriterMetadataUtils.WriteCategory(this.writer, typeName, AtomConstants.ODataSchemeNamespace, null); } Uri editLink = entry.EditLink; if (editLink != null) { // <link rel="edit" title="Title" href="LinkHRef"/> ODataAtomWriterUtils.WriteReadOrEditLink(this.writer, this.BaseUri, editLink, AtomConstants.AtomEditRelationAttributeValue, typeName); } Uri readLink = entry.ReadLink; if (readLink != null) { // <link rel="self" title="Title" href="LinkHRef"/> ODataAtomWriterUtils.WriteReadOrEditLink(this.writer, this.BaseUri, readLink, AtomConstants.AtomSelfRelationAttributeValue, typeName); } // named streams IEnumerable <ODataMediaResource> namedStreams = entry.NamedStreams; if (namedStreams != null) { foreach (ODataMediaResource namedStream in namedStreams) { ValidationUtils.ValidateNamedStream(namedStream, this.Version); ODataAtomWriterUtils.WriteNamedStream(this.writer, this.BaseUri, namedStream); } } // association links IEnumerable <ODataAssociationLink> associationLinks = entry.AssociationLinks; if (associationLinks != null) { foreach (ODataAssociationLink associationLink in associationLinks) { ValidationUtils.ValidateAssociationLink(associationLink, this.Version); ODataAtomWriterUtils.WriteAssociationLink(this.writer, this.BaseUri, entry, associationLink); } } // write entry metadata including syndication EPM AtomEntryMetadata epmEntryMetadata = null; if (epmResourceTypeAnnotation != null) { ODataVersionChecker.CheckEntityPropertyMapping(this.Version, entryType); epmEntryMetadata = EpmSyndicationWriter.WriteEntryEpm( epmResourceTypeAnnotation.EpmTargetTree, propertyValueCache, entryType, this.MetadataProvider, this.Version); } ODataAtomWriterMetadataUtils.WriteEntryMetadata(this.writer, this.BaseUri, entry, epmEntryMetadata); // write the content this.WriteEntryContent(entry, entryType, propertyValueCache, epmResourceTypeAnnotation == null ? null : epmResourceTypeAnnotation.EpmSourceTree.Root); // write custom EPM if (epmResourceTypeAnnotation != null) { EpmCustomWriter.WriteEntryEpm( this.writer, epmResourceTypeAnnotation.EpmTargetTree, propertyValueCache, entryType, this.MetadataProvider); } // </entry> this.writer.WriteEndElement(); }