/// <summary>
        /// Set a property of atom:contributor element. atom:contributor is created if does not exist.
        /// </summary>
        /// <param name="propertyToSet">Property to be set.</param>
        /// <param name="textPropertyValue">Value of the property.</param>
        private void SetContributorProperty(SyndicationItemProperty propertyToSet, string textPropertyValue)
        {
            if (this.Target.Contributors.Count == 0)
            {
                this.Target.Contributors.Add(new SyndicationPerson());
            }

            // We can have at most one contributor
            switch (propertyToSet)
            {
            case SyndicationItemProperty.ContributorEmail:
                this.Target.Contributors[0].Email = textPropertyValue;
                break;

            case SyndicationItemProperty.ContributorName:
                this.Target.Contributors[0].Name = textPropertyValue;
                break;

            case SyndicationItemProperty.ContributorUri:
                this.Target.Contributors[0].Uri = textPropertyValue;
                break;

            default:
                Debug.Fail("propertyToSet is not a Contributor property.");
                break;
            }

            Debug.Assert(this.Target.Contributors.Count == 1, "There should be one and only one contributor.");
        }
 public EntityPropertyMappingAttribute(string sourcePath, string targetPath, string targetNamespacePrefix, string targetNamespaceUri, bool keepInContent)
 {
     Uri uri;
     if (string.IsNullOrEmpty(sourcePath))
     {
         throw new ArgumentException(Strings.EntityPropertyMapping_EpmAttribute("sourcePath"));
     }
     this.sourcePath = sourcePath;
     if (string.IsNullOrEmpty(targetPath))
     {
         throw new ArgumentException(Strings.EntityPropertyMapping_EpmAttribute("targetPath"));
     }
     if (targetPath[0] == '@')
     {
         throw new ArgumentException(Strings.EntityPropertyMapping_InvalidTargetPath(targetPath));
     }
     this.targetPath = targetPath;
     this.targetSyndicationItem = SyndicationItemProperty.CustomProperty;
     this.targetTextContentKind = SyndicationTextContentKind.Plaintext;
     this.targetNamespacePrefix = targetNamespacePrefix;
     if (string.IsNullOrEmpty(targetNamespaceUri))
     {
         throw new ArgumentException(Strings.EntityPropertyMapping_EpmAttribute("targetNamespaceUri"));
     }
     this.targetNamespaceUri = targetNamespaceUri;
     if (!Uri.TryCreate(targetNamespaceUri, UriKind.Absolute, out uri))
     {
         throw new ArgumentException(Strings.EntityPropertyMapping_TargetNamespaceUriNotValid(targetNamespaceUri));
     }
     this.keepInContent = keepInContent;
 }
        public EntityPropertyMappingAttribute(string sourcePath, string targetPath, string targetNamespacePrefix, string targetNamespaceUri, bool keepInContent)
        {
            Uri uri;

            if (string.IsNullOrEmpty(sourcePath))
            {
                throw new ArgumentException(Strings.EntityPropertyMapping_EpmAttribute("sourcePath"));
            }
            this.sourcePath = sourcePath;
            if (string.IsNullOrEmpty(targetPath))
            {
                throw new ArgumentException(Strings.EntityPropertyMapping_EpmAttribute("targetPath"));
            }
            if (targetPath[0] == '@')
            {
                throw new ArgumentException(Strings.EntityPropertyMapping_InvalidTargetPath(targetPath));
            }
            this.targetPath            = targetPath;
            this.targetSyndicationItem = SyndicationItemProperty.CustomProperty;
            this.targetTextContentKind = SyndicationTextContentKind.Plaintext;
            this.targetNamespacePrefix = targetNamespacePrefix;
            if (string.IsNullOrEmpty(targetNamespaceUri))
            {
                throw new ArgumentException(Strings.EntityPropertyMapping_EpmAttribute("targetNamespaceUri"));
            }
            this.targetNamespaceUri = targetNamespaceUri;
            if (!Uri.TryCreate(targetNamespaceUri, UriKind.Absolute, out uri))
            {
                throw new ArgumentException(Strings.EntityPropertyMapping_TargetNamespaceUriNotValid(targetNamespaceUri));
            }
            this.keepInContent = keepInContent;
        }
Пример #4
0
 /// <summary>
 /// Returns a value indicating whether the given syndication item property supports extension attributes
 /// </summary>
 /// <param name="itemProperty">The syndication item property</param>
 /// <returns>True if the property is Title, Summary, Rights, or Custom</returns>
 public static bool SupportsExtensionAttributes(this SyndicationItemProperty itemProperty)
 {
     return(itemProperty == SyndicationItemProperty.Title ||
            itemProperty == SyndicationItemProperty.Summary ||
            itemProperty == SyndicationItemProperty.Rights ||
            itemProperty == SyndicationItemProperty.CustomProperty);
 }
        /// <summary>
        /// Given a <paramref name="targetPath"/> gets the corresponding syndication property.
        /// </summary>
        /// <param name="targetPath">Target path in the form of syndication property name</param>
        /// <returns>
        /// Enumerated value of a SyndicationItemProperty or SyndicationItemProperty.CustomProperty if the <paramref name="targetPath"/>
        /// does not map to any syndication property name.
        /// </returns>
        private static SyndicationItemProperty MapEpmTargetPathToSyndicationProperty(String targetPath)
        {
            Debug.Assert(Enum.GetNames(typeof(SyndicationItemProperty)).Count() == 12, "Any addition to SyndicationItemPropery enum requires updating this method.");

            SyndicationItemProperty targetSyndicationItem = SyndicationItemProperty.CustomProperty;

            switch (targetPath)
            {
            case System.Data.Services.XmlConstants.SyndAuthorEmail:
                targetSyndicationItem = SyndicationItemProperty.AuthorEmail;
                break;

            case System.Data.Services.XmlConstants.SyndAuthorName:
                targetSyndicationItem = SyndicationItemProperty.AuthorName;
                break;

            case System.Data.Services.XmlConstants.SyndAuthorUri:
                targetSyndicationItem = SyndicationItemProperty.AuthorUri;
                break;

            case System.Data.Services.XmlConstants.SyndContributorEmail:
                targetSyndicationItem = SyndicationItemProperty.ContributorEmail;
                break;

            case System.Data.Services.XmlConstants.SyndContributorName:
                targetSyndicationItem = SyndicationItemProperty.ContributorName;
                break;

            case System.Data.Services.XmlConstants.SyndContributorUri:
                targetSyndicationItem = SyndicationItemProperty.ContributorUri;
                break;

            case System.Data.Services.XmlConstants.SyndUpdated:
                targetSyndicationItem = SyndicationItemProperty.Updated;
                break;

            case System.Data.Services.XmlConstants.SyndPublished:
                targetSyndicationItem = SyndicationItemProperty.Published;
                break;

            case System.Data.Services.XmlConstants.SyndRights:
                targetSyndicationItem = SyndicationItemProperty.Rights;
                break;

            case System.Data.Services.XmlConstants.SyndSummary:
                targetSyndicationItem = SyndicationItemProperty.Summary;
                break;

            case System.Data.Services.XmlConstants.SyndTitle:
                targetSyndicationItem = SyndicationItemProperty.Title;
                break;

            default:
                targetSyndicationItem = SyndicationItemProperty.CustomProperty;
                break;
            }

            return(targetSyndicationItem);
        }
Пример #6
0
 public static string ToElementOrAttributeName(this SyndicationItemProperty itemProperty)
 {
     return(itemProperty.ToString().ToLowerInvariant()
            .Replace(ODataConstants.LinkElementName, string.Empty)
            .Replace(ODataConstants.CategoryElementName, string.Empty)
            .Replace(ODataConstants.AuthorElementName, string.Empty)
            .Replace(ODataConstants.ContributorElementName, string.Empty));
 }
Пример #7
0
        private static DateTimeOffset CreateDateTimeValue(object propertyValue, SyndicationItemProperty targetProperty, ODataWriterBehavior writerBehavior)
        {
            Debug.Assert(
                writerBehavior.FormatBehaviorKind != ODataBehaviorKind.WcfDataServicesClient,
                "CreateDateTimeValue should not be used in WCF DS client mode.");

            if (propertyValue == null)
            {
                return(DateTimeOffset.Now);
            }

            if (propertyValue is DateTimeOffset)
            {
                return((DateTimeOffset)propertyValue);
            }

            if (propertyValue is DateTime)
            {
                // DateTimeOffset takes care of DateTimes of Unspecified kind so we won't end up
                // with datetime without timezone info mapped to atom:updated or atom:published element.
                return(new DateTimeOffset((DateTime)propertyValue));
            }

            string stringValue = propertyValue as string;

            if (stringValue != null)
            {
                DateTimeOffset date;
                if (!DateTimeOffset.TryParse(stringValue, out date))
                {
                    DateTime result;
                    if (!DateTime.TryParse(stringValue, out result))
                    {
                        throw new ODataException(o.Strings.EpmSyndicationWriter_DateTimePropertyCanNotBeConverted(targetProperty.ToString()));
                    }

                    return(new DateTimeOffset(result));
                }

                return(date);
            }

            try
            {
                return(new DateTimeOffset(Convert.ToDateTime(propertyValue, CultureInfo.InvariantCulture)));
            }
            catch (Exception e)
            {
                if (!ExceptionUtils.IsCatchableExceptionType(e))
                {
                    throw;
                }

                throw new ODataException(o.Strings.EpmSyndicationWriter_DateTimePropertyCanNotBeConverted(targetProperty.ToString()));
            }
        }
 public EntityPropertyMappingAttribute(string sourcePath, SyndicationItemProperty targetSyndicationItem, SyndicationTextContentKind targetTextContentKind, bool keepInContent)
 {
     if (string.IsNullOrEmpty(sourcePath))
     {
         throw new ArgumentException(Strings.EntityPropertyMapping_EpmAttribute("sourcePath"));
     }
     this.sourcePath = sourcePath;
     this.targetPath = targetSyndicationItem.ToTargetPath();
     this.targetSyndicationItem = targetSyndicationItem;
     this.targetTextContentKind = targetTextContentKind;
     this.targetNamespacePrefix = "atom";
     this.targetNamespaceUri = "http://www.w3.org/2005/Atom";
     this.keepInContent = keepInContent;
 }
 public EntityPropertyMappingAttribute(string sourcePath, SyndicationItemProperty targetSyndicationItem, SyndicationTextContentKind targetTextContentKind, bool keepInContent)
 {
     if (string.IsNullOrEmpty(sourcePath))
     {
         throw new ArgumentException(Strings.EntityPropertyMapping_EpmAttribute("sourcePath"));
     }
     this.sourcePath            = sourcePath;
     this.targetPath            = targetSyndicationItem.ToTargetPath();
     this.targetSyndicationItem = targetSyndicationItem;
     this.targetTextContentKind = targetTextContentKind;
     this.targetNamespacePrefix = "atom";
     this.targetNamespaceUri    = "http://www.w3.org/2005/Atom";
     this.keepInContent         = keepInContent;
 }
Пример #10
0
        public static string ToParentElementName(this SyndicationItemProperty itemProperty)
        {
            string[] parentElements = new[] { ODataConstants.LinkElementName, ODataConstants.CategoryElementName, ODataConstants.AuthorElementName, ODataConstants.ContributorElementName };
            var      stringValue    = itemProperty.ToString().ToLowerInvariant();

            foreach (var parent in parentElements)
            {
                if (stringValue.StartsWith(parent, StringComparison.Ordinal))
                {
                    return(parent);
                }
            }

            return(null);
        }
        public EntityPropertyMappingAttribute(String sourcePath, SyndicationItemProperty targetSyndicationItem, SyndicationTextContentKind targetTextContentKind, bool keepInContent)
        {
            if (String.IsNullOrEmpty(sourcePath))
            {
                throw new ArgumentException(Strings.EntityPropertyMapping_EpmAttribute("sourcePath"));
            }

            this.sourcePath            = sourcePath;
            this.targetPath            = SyndicationItemPropertyToPath(targetSyndicationItem);
            this.targetSyndicationItem = targetSyndicationItem;
            this.targetTextContentKind = targetTextContentKind;
            this.targetNamespacePrefix = EntityPropertyMappingAttribute.AtomNamespacePrefix;
            this.targetNamespaceUri    = XmlConstants.AtomNamespace;
            this.keepInContent         = keepInContent;
        }
        /// <summary>
        /// Used for mapping a resource property to syndication content
        /// </summary>
        /// <param name="sourcePath">Source property path</param>
        /// <param name="targetSyndicationItem">Syndication item to which the <see cref="sourcePath"/> is mapped</param>
        /// <param name="targetTextContentKind">Syndication content kind for <see cref="targetSyndicationItem"/></param>
        /// <param name="keepInContent">If true the property value is kept in the content section as before,
        /// when false the property value is only placed at the mapped location</param>
        public EntityPropertyMappingAttribute(String sourcePath, SyndicationItemProperty targetSyndicationItem, SyndicationTextContentKind targetTextContentKind, bool keepInContent)
        {
            if (String.IsNullOrEmpty(sourcePath))
            {
                throw new ArgumentException(Strings.EntityPropertyMapping_EpmAttribute("sourcePath"));
            }

            this.sourcePath            = sourcePath;
            this.targetPath            = SyndicationItemPropertyToPath(targetSyndicationItem);
            this.targetSyndicationItem = targetSyndicationItem;
            this.targetTextContentKind = targetTextContentKind;
            this.targetNamespacePrefix = EntityPropertyMappingAttribute.AtomNamespacePrefix;
            this.targetNamespaceUri    = XmlConstants.AtomNamespace;
            this.keepInContent         = keepInContent;
        }
Пример #13
0
        /// <summary>
        /// Creates a Syndication EPM annotation on the <paramref name="annotatable"/>.
        /// </summary>
        /// <typeparam name="T">The type of the annotatable being passed in.</typeparam>
        /// <param name="annotatable">The annotatable to add the EPM annotation to.</param>
        /// <param name="sourcePath">The source path to be used in the mapping.</param>
        /// <param name="targetSyndicationItem">The syndication item to be used in the mapping (defaults to AuthorName).</param>
        /// <param name="targetTextContentKind">The target content kind (defaults to plain text).</param>
        /// <param name="keepInContent">true to keep the mapped value in content; otherwise false (defaults to true).</param>
        /// <returns>The <paramref name="annotatable"/> being passed in for composability.</returns>
        public static T EntityPropertyMapping <T>(
            this T annotatable,
            string sourcePath,
            SyndicationItemProperty targetSyndicationItem    = SyndicationItemProperty.AuthorName,
            SyndicationTextContentKind targetTextContentKind = SyndicationTextContentKind.Plaintext,
            bool keepInContent = true) where T : AnnotatedItem
        {
            ExceptionUtilities.CheckArgumentNotNull(annotatable, "annotatable");
            ExceptionUtilities.CheckArgumentNotNull(sourcePath, "sourcePath");

            ExceptionUtilities.Assert(annotatable is EntityType, "Entity Property Mappings should only be applied to entity types");

            annotatable.Add(new PropertyMappingAnnotation(sourcePath, targetSyndicationItem, targetTextContentKind, keepInContent));
            return(annotatable);
        }
Пример #14
0
        private static EntityPropertyMappingAttribute ValidateAnnotationValues(EpmAnnotationValues annotationValues, string typeName, IEdmProperty property)
        {
            if (annotationValues.TargetPath == null)
            {
                string str     = "FC_TargetPath" + annotationValues.AttributeSuffix;
                string message = (property == null) ? Microsoft.Data.OData.Strings.EpmExtensionMethods_MissingAttributeOnType(str, typeName) : Microsoft.Data.OData.Strings.EpmExtensionMethods_MissingAttributeOnProperty(str, property.Name, typeName);
                throw new ODataException(message);
            }
            bool result = true;

            if ((annotationValues.KeepInContent != null) && !bool.TryParse(annotationValues.KeepInContent, out result))
            {
                string str3 = "FC_KeepInContent" + annotationValues.AttributeSuffix;
                throw new InvalidOperationException((property == null) ? Microsoft.Data.OData.Strings.EpmExtensionMethods_InvalidKeepInContentOnType(str3, typeName) : Microsoft.Data.OData.Strings.EpmExtensionMethods_InvalidKeepInContentOnProperty(str3, property.Name, typeName));
            }
            SyndicationItemProperty targetSyndicationItem = MapTargetPathToSyndicationProperty(annotationValues.TargetPath);

            if (targetSyndicationItem == SyndicationItemProperty.CustomProperty)
            {
                if (annotationValues.ContentKind != null)
                {
                    string str4 = "FC_ContentKind" + annotationValues.AttributeSuffix;
                    string str5 = (property == null) ? Microsoft.Data.OData.Strings.EpmExtensionMethods_AttributeNotAllowedForCustomMappingOnType(str4, typeName) : Microsoft.Data.OData.Strings.EpmExtensionMethods_AttributeNotAllowedForCustomMappingOnProperty(str4, property.Name, typeName);
                    throw new ODataException(str5);
                }
                return(new EntityPropertyMappingAttribute(annotationValues.SourcePath, annotationValues.TargetPath, annotationValues.NamespacePrefix, annotationValues.NamespaceUri, result));
            }
            if (annotationValues.NamespaceUri != null)
            {
                string str6 = "FC_NsUri" + annotationValues.AttributeSuffix;
                string str7 = (property == null) ? Microsoft.Data.OData.Strings.EpmExtensionMethods_AttributeNotAllowedForAtomPubMappingOnType(str6, typeName) : Microsoft.Data.OData.Strings.EpmExtensionMethods_AttributeNotAllowedForAtomPubMappingOnProperty(str6, property.Name, typeName);
                throw new ODataException(str7);
            }
            if (annotationValues.NamespacePrefix != null)
            {
                string str8 = "FC_NsPrefix" + annotationValues.AttributeSuffix;
                string str9 = (property == null) ? Microsoft.Data.OData.Strings.EpmExtensionMethods_AttributeNotAllowedForAtomPubMappingOnType(str8, typeName) : Microsoft.Data.OData.Strings.EpmExtensionMethods_AttributeNotAllowedForAtomPubMappingOnProperty(str8, property.Name, typeName);
                throw new ODataException(str9);
            }
            SyndicationTextContentKind plaintext = SyndicationTextContentKind.Plaintext;

            if (annotationValues.ContentKind != null)
            {
                plaintext = MapContentKindToSyndicationTextContentKind(annotationValues.ContentKind, annotationValues.AttributeSuffix, typeName, (property == null) ? null : property.Name);
            }
            return(new EntityPropertyMappingAttribute(annotationValues.SourcePath, targetSyndicationItem, plaintext, result));
        }
Пример #15
0
        private static DateTimeOffset CreateDateTimeValue(object propertyValue, SyndicationItemProperty targetProperty, ODataWriterBehavior writerBehavior)
        {
            DateTimeOffset offset;
            DateTime       time;

            if (propertyValue == null)
            {
                return(DateTimeOffset.Now);
            }
            if (propertyValue is DateTimeOffset)
            {
                return((DateTimeOffset)propertyValue);
            }
            if (propertyValue is DateTime)
            {
                return(new DateTimeOffset((DateTime)propertyValue));
            }
            string input = propertyValue as string;

            if (input == null)
            {
                DateTimeOffset offset2;
                try
                {
                    offset2 = new DateTimeOffset(Convert.ToDateTime(propertyValue, CultureInfo.InvariantCulture));
                }
                catch (Exception exception)
                {
                    if (!ExceptionUtils.IsCatchableExceptionType(exception))
                    {
                        throw;
                    }
                    throw new ODataException(Microsoft.Data.OData.Strings.EpmSyndicationWriter_DateTimePropertyCanNotBeConverted(targetProperty.ToString()));
                }
                return(offset2);
            }
            if (DateTimeOffset.TryParse(input, out offset))
            {
                return(offset);
            }
            if (!DateTime.TryParse(input, out time))
            {
                throw new ODataException(Microsoft.Data.OData.Strings.EpmSyndicationWriter_DateTimePropertyCanNotBeConverted(targetProperty.ToString()));
            }
            return(new DateTimeOffset(time));
        }
Пример #16
0
        /// <summary>
        /// Applies EPM mapping to the specified entity type on the model and returns it for composablity.
        /// </summary>
        /// <param name="model">Model to use</param>
        /// <param name="entityTypeName">Entity type name</param>
        /// <param name="sourcePath">Source path</param>
        /// <param name="targetSyndicationItem">TargetSyndicationItem to use</param>
        /// <param name="targetTextContentKind">TargetTextContentKind to use</param>
        /// <param name="keepInContent">true to keep the mapped value in content; otherwise false (defaults to true).</param>
        /// <returns>Enity Model Schema with the mapping applied</returns>
        public static EntityModelSchema EntityPropertyMapping(
            this EntityModelSchema model,
            string entityTypeName,
            string sourcePath,
            SyndicationItemProperty targetSyndicationItem    = SyndicationItemProperty.AuthorName,
            SyndicationTextContentKind targetTextContentKind = SyndicationTextContentKind.Plaintext,
            bool keepInContent = true)
        {
            ExceptionUtilities.CheckArgumentNotNull(model, "model");
            ExceptionUtilities.CheckArgumentNotNull(entityTypeName, "entityTypeName");
            ExceptionUtilities.CheckArgumentNotNull(sourcePath, "sourcePath");
            var entityType = model.GetEntityType(entityTypeName);

            ExceptionUtilities.CheckObjectNotNull(entityType, "There are no entity types matching the name:{0} in the model", entityTypeName);
            entityType.EntityPropertyMapping(sourcePath, targetSyndicationItem, targetTextContentKind, keepInContent);

            return(model);
        }
Пример #17
0
 private static DateTimeOffset CreateDateTimeValue(object propertyValue, SyndicationItemProperty targetProperty, ODataWriterBehavior writerBehavior)
 {
     DateTimeOffset offset;
     DateTime time;
     if (propertyValue == null)
     {
         return DateTimeOffset.Now;
     }
     if (propertyValue is DateTimeOffset)
     {
         return (DateTimeOffset) propertyValue;
     }
     if (propertyValue is DateTime)
     {
         return new DateTimeOffset((DateTime) propertyValue);
     }
     string input = propertyValue as string;
     if (input == null)
     {
         DateTimeOffset offset2;
         try
         {
             offset2 = new DateTimeOffset(Convert.ToDateTime(propertyValue, CultureInfo.InvariantCulture));
         }
         catch (Exception exception)
         {
             if (!ExceptionUtils.IsCatchableExceptionType(exception))
             {
                 throw;
             }
             throw new ODataException(Microsoft.Data.OData.Strings.EpmSyndicationWriter_DateTimePropertyCanNotBeConverted(targetProperty.ToString()));
         }
         return offset2;
     }
     if (DateTimeOffset.TryParse(input, out offset))
     {
         return offset;
     }
     if (!DateTime.TryParse(input, out time))
     {
         throw new ODataException(Microsoft.Data.OData.Strings.EpmSyndicationWriter_DateTimePropertyCanNotBeConverted(targetProperty.ToString()));
     }
     return new DateTimeOffset(time);
 }
        /// <summary>
        /// Maps the enumeration of allowed <see cref="SyndicationItemProperty"/> values to their string representations
        /// </summary>
        /// <param name="targetSyndicationItem">Value of the <see cref="SyndicationItemProperty"/> given in
        /// the <see cref="EntityPropertyMappingAttribute"/> contstructor</param>
        /// <returns>String representing the xml element path in the syndication property</returns>
        internal static String SyndicationItemPropertyToPath(SyndicationItemProperty targetSyndicationItem)
        {
            switch (targetSyndicationItem)
            {
            case SyndicationItemProperty.AuthorEmail:
                return("author/email");

            case SyndicationItemProperty.AuthorName:
                return("author/name");

            case SyndicationItemProperty.AuthorUri:
                return("author/uri");

            case SyndicationItemProperty.ContributorEmail:
                return("contributor/email");

            case SyndicationItemProperty.ContributorName:
                return("contributor/name");

            case SyndicationItemProperty.ContributorUri:
                return("contributor/uri");

            case SyndicationItemProperty.Updated:
                return("updated");

            case SyndicationItemProperty.Published:
                return("published");

            case SyndicationItemProperty.Rights:
                return("rights");

            case SyndicationItemProperty.Summary:
                return("summary");

            case SyndicationItemProperty.Title:
                return("title");

            default:
                throw new ArgumentException(Strings.EntityPropertyMapping_EpmAttribute("targetSyndicationItem"));
            }
        }
        /// <summary>
        /// Used for conditional mapping to atom:link[@href] and atom:category[@term].
        /// </summary>
        /// <param name="sourcePath">Source property path.</param>
        /// <param name="targetSyndicationItem">Syndication item to which the <see cref="sourcePath"/> is mapped.</param>
        /// <param name="keepInContent">If true the property value is kept in the content section as before,
        /// when false the property value is only placed at the mapped location.</param>
        /// <param name="criteriaValue">Criteria value that is used as a condition.</param>
        public EntityPropertyMappingAttribute(String sourcePath, SyndicationItemProperty targetSyndicationItem, bool keepInContent, String criteriaValue)
        {
            if (String.IsNullOrEmpty(sourcePath))
            {
                throw new ArgumentException(Strings.EntityPropertyMapping_EpmAttribute("sourcePath"));
            }

            this.sourcePath = sourcePath;

            if (String.IsNullOrEmpty(criteriaValue))
            {
                throw new ArgumentException(Strings.EntityPropertyMapping_EpmAttribute("criteriaValue"));
            }

            this.criteriaValue         = criteriaValue;
            this.targetPath            = SyndicationItemPropertyToPath(targetSyndicationItem);
            this.targetSyndicationItem = targetSyndicationItem;
            this.targetTextContentKind = SyndicationTextContentKind.Plaintext;
            this.targetNamespacePrefix = AtomConstants.NonEmptyAtomNamespacePrefix;
            this.targetNamespaceUri    = AtomConstants.AtomNamespace;
            this.keepInContent         = keepInContent;
        }
Пример #20
0
        private static string ToAttributeValue(this SyndicationItemProperty syndicationItemProperty)
        {
            switch (syndicationItemProperty)
            {
            case SyndicationItemProperty.AuthorEmail:
                return("SyndicationAuthorEmail");

            case SyndicationItemProperty.AuthorName:
                return("SyndicationAuthorName");

            case SyndicationItemProperty.AuthorUri:
                return("SyndicationAuthorUri");

            case SyndicationItemProperty.ContributorEmail:
                return("SyndicationContributorEmail");

            case SyndicationItemProperty.ContributorName:
                return("SyndicationContributorName");

            case SyndicationItemProperty.ContributorUri:
                return("SyndicationContributorUri");

            case SyndicationItemProperty.Updated:
                return("SyndicationUpdated");

            case SyndicationItemProperty.Published:
                return("SyndicationPublished");

            case SyndicationItemProperty.Rights:
                return("SyndicationRights");

            case SyndicationItemProperty.Summary:
                return("SyndicationSummary");

            case SyndicationItemProperty.Title:
                return("SyndicationTitle");
            }
            throw new ODataException(Microsoft.Data.OData.Strings.General_InternalError(InternalErrorCodes.EpmExtensionMethods_ToAttributeValue_SyndicationItemProperty));
        }
Пример #21
0
        public PropertyMappingAnnotation(
            string sourcePath,
            SyndicationItemProperty targetSyndicationItem,
            SyndicationTextContentKind targetTextContentKind,
            bool keepInContent)
            : this(sourcePath, keepInContent)
        {
            this.SyndicationItemProperty    = targetSyndicationItem;
            this.SyndicationTextContentKind = targetTextContentKind;

            this.TargetPath = targetSyndicationItem.ToString().ToLowerInvariant();
            if (this.TargetPath.StartsWith(ODataConstants.AuthorElementName, StringComparison.Ordinal))
            {
                this.TargetPath = this.TargetPath.Insert(ODataConstants.AuthorElementName.Length, "/");
            }
            else if (this.TargetPath.StartsWith(ODataConstants.ContributorElementName, StringComparison.Ordinal))
            {
                this.TargetPath = this.TargetPath.Insert(ODataConstants.ContributorElementName.Length, "/");
            }

            this.TargetNamespacePrefix = null;
            this.TargetNamespaceUri    = ODataConstants.AtomNamespaceName;
        }
        public PropertyMappingAnnotation(
            string sourcePath,
            SyndicationItemProperty targetSyndicationItem,
            SyndicationTextContentKind targetTextContentKind,
            bool keepInContent)
            : this(sourcePath, keepInContent)
        {
            this.SyndicationItemProperty = targetSyndicationItem;
            this.SyndicationTextContentKind = targetTextContentKind;

            this.TargetPath = targetSyndicationItem.ToString().ToLowerInvariant();
            if (this.TargetPath.StartsWith(ODataConstants.AuthorElementName, StringComparison.Ordinal))
            {
                this.TargetPath = this.TargetPath.Insert(ODataConstants.AuthorElementName.Length, "/");
            }
            else if (this.TargetPath.StartsWith(ODataConstants.ContributorElementName, StringComparison.Ordinal))
            {
                this.TargetPath = this.TargetPath.Insert(ODataConstants.ContributorElementName.Length, "/");
            }

            this.TargetNamespacePrefix = null;
            this.TargetNamespaceUri = ODataConstants.AtomNamespaceName;
        }
Пример #23
0
 internal static string MapSyndicationPropertyToEpmTargetPath(SyndicationItemProperty property)
 {
     return syndicationItemToTargetPath[(int) property];
 }
 /// <summary>
 /// Maps the enumeration of allowed <see cref="SyndicationItemProperty"/> values to their string representations
 /// </summary>
 /// <param name="targetSyndicationItem">Value of the <see cref="SyndicationItemProperty"/> given in 
 /// the <see cref="EntityPropertyMappingAttribute"/> contstructor</param>
 /// <returns>String representing the xml element path in the syndication property</returns>
 internal static String SyndicationItemPropertyToPath(SyndicationItemProperty targetSyndicationItem)
 {
     switch (targetSyndicationItem)
     {
         case SyndicationItemProperty.AuthorEmail:
             return "author/email";
         case SyndicationItemProperty.AuthorName:
             return "author/name";
         case SyndicationItemProperty.AuthorUri:
             return "author/uri";
         case SyndicationItemProperty.ContributorEmail:
             return "contributor/email";
         case SyndicationItemProperty.ContributorName:
             return "contributor/name";
         case SyndicationItemProperty.ContributorUri:
             return "contributor/uri";
         case SyndicationItemProperty.Updated:
             return "updated";
         case SyndicationItemProperty.Published:
             return "published";
         case SyndicationItemProperty.Rights:
             return "rights";
         case SyndicationItemProperty.Summary:
             return "summary";
         case SyndicationItemProperty.Title:
             return "title";
         default:
             throw new ArgumentException(Strings.EntityPropertyMapping_EpmAttribute("targetSyndicationItem"));
     }
 }
Пример #25
0
        internal void Add(EntityPropertyMappingInfo epmInfo)
        {
            DebugUtils.CheckNoExternalCallers();

            List <EpmSourcePathSegment> pathToCurrentSegment = new List <EpmSourcePathSegment>();
            EpmSourcePathSegment        currentSourceSegment = this.Root;
            EpmSourcePathSegment        foundSourceSegment   = null;
            ResourceType         currentType = epmInfo.ActualPropertyType;
            EpmSourcePathSegment multiValuePropertySegment = null;

            Debug.Assert(!string.IsNullOrEmpty(epmInfo.Attribute.SourcePath), "Invalid source path");
            string[] propertyPath = epmInfo.Attribute.SourcePath.Split('/');

            if (epmInfo.CriteriaValue != null)
            {
                ValidateConditionalMapping(epmInfo);
            }

            Debug.Assert(propertyPath.Length > 0, "Must have been validated during EntityPropertyMappingAttribute construction");
            for (int sourcePropertyIndex = 0; sourcePropertyIndex < propertyPath.Length; sourcePropertyIndex++)
            {
                string propertyName = propertyPath[sourcePropertyIndex];

                if (propertyName.Length == 0)
                {
                    throw new ODataException(Strings.EpmSourceTree_InvalidSourcePath(epmInfo.DefiningType.Name, epmInfo.Attribute.SourcePath));
                }

                bool isMultiValueProperty;
                currentType = GetPropertyType(currentType, propertyName, out isMultiValueProperty);

                foundSourceSegment = currentSourceSegment.SubProperties.SingleOrDefault(e => e.PropertyName == propertyName);
                if (foundSourceSegment != null)
                {
                    currentSourceSegment = foundSourceSegment;
                }
                else
                {
                    EpmSourcePathSegment newSourceSegment = new EpmSourcePathSegment(propertyName);
                    currentSourceSegment.SubProperties.Add(newSourceSegment);
                    currentSourceSegment = newSourceSegment;
                }

                pathToCurrentSegment.Add(currentSourceSegment);

                if (isMultiValueProperty)
                {
                    Debug.Assert(
                        currentSourceSegment.EpmInfo == null || currentSourceSegment.EpmInfo.MultiValueStatus == EntityPropertyMappingMultiValueStatus.MultiValueProperty,
                        "MultiValue property must have EpmInfo marked as MultiValue or none at all.");
                    Debug.Assert(
                        currentSourceSegment.EpmInfo != null || foundSourceSegment == null,
                        "The only way to get a propety without info attached yet on a MultiValue property is when we just created it.");

                    if (multiValuePropertySegment != null)
                    {
                        // Nested MultiValue - not allowed to be mapped
                        throw new ODataException(Strings.EpmSourceTree_NestedMultiValue(
                                                     multiValuePropertySegment.EpmInfo.Attribute.SourcePath,
                                                     multiValuePropertySegment.EpmInfo.DefiningType.Name,
                                                     epmInfo.Attribute.SourcePath));
                    }

                    multiValuePropertySegment = currentSourceSegment;

                    // MultiValue properties can only be mapped to a top-level element, so we can blindly use the first part
                    //   of the target path as the target path for the MultiValue property.
                    Debug.Assert(!string.IsNullOrEmpty(epmInfo.Attribute.TargetPath), "Target path should have been checked by the EpmAttribute constructor.");
                    string multiValuePropertyTargetPath = epmInfo.Attribute.TargetPath.Split('/')[0];

                    if (currentSourceSegment.EpmInfo == null || !currentSourceSegment.EpmInfo.DefiningTypesAreEqual(epmInfo))
                    {
                        if (currentSourceSegment.EpmInfo != null)
                        {
                            Debug.Assert(!currentSourceSegment.EpmInfo.DefiningTypesAreEqual(epmInfo), "Just verifying that the ifs are correct.");
                            Debug.Assert(foundSourceSegment != null, "Can't have existing node with EpmInfo on it here and not found it before.");

                            // If the MultiValue property we're trying to add is from a different type than the one we already have
                            //   just overwrite the epm info. This means that the derived type defines a different mapping for the property than the base type.
                            //   We also need to walk all the children of the base type mapping here and remove them from the target tree
                            //   since we're overriding the entire MultiValue property mapping (not just one item property)
                            // Note that for MultiValue properties, removing the MultiValue property node itself will remove all the MultiValue item properties as well
                            //   as they have to be children of the MultiValue property node in the target tree.
                            this.epmTargetTree.Remove(foundSourceSegment.EpmInfo);

                            // We also need to remove all children of the MultiValue property node from the source tree
                            //   as the derived type is overriding it completely. If the derived type doesn't override all of the properties
                            //   we should fail as if it did't map all of them.
                            currentSourceSegment.SubProperties.Clear();
                        }

                        // This is the first time we've seen this MultiValue property mapped
                        //   (on this type, we might have seen it on the base type, but that has been removed)

                        // The source path is the path we have so far for the property
                        string multiValuePropertySourcePath = string.Join("/", propertyPath, 0, sourcePropertyIndex + 1);

                        if (!epmInfo.IsSyndicationMapping)
                        {
                            // Custom EPM for MultiValue is not supported yet
                            // Note: This has already been implemented, but then removed from the code. To see what it takes to implement this
                            //   please see the change which adds this comment into the sources.
                            throw new ODataException(Strings.EpmSourceTree_MultiValueNotAllowedInCustomMapping(
                                                         multiValuePropertySourcePath,
                                                         epmInfo.DefiningType.Name));
                        }

                        // Create a new EPM attribute to represent the MultiValue property mapping
                        //   note that this attribute is basically implicitly declared whenever the user declares EPM attribute
                        //   for a property from some MultiValue property. (the declaration happens right here)
                        EntityPropertyMappingAttribute multiValueEpmAttribute = new EntityPropertyMappingAttribute(
                            multiValuePropertySourcePath,
                            multiValuePropertyTargetPath,
                            epmInfo.Attribute.TargetNamespacePrefix,
                            epmInfo.Attribute.TargetNamespaceUri,
                            epmInfo.Attribute.KeepInContent);

                        // Create a special EpmInfo from the above special attribute which represents just the MultiValue property itself
                        EntityPropertyMappingInfo multiValueEpmInfo = new EntityPropertyMappingInfo(
                            multiValueEpmAttribute,
                            epmInfo.DefiningType,
                            epmInfo.ActualPropertyType);
                        multiValueEpmInfo.MultiValueStatus   = EntityPropertyMappingMultiValueStatus.MultiValueProperty;
                        multiValueEpmInfo.MultiValueItemType = currentType;

                        // We need to mark the info as syndication/custom mapping explicitely since the attribute we create (From which it's infered) is always custom mapping
                        Debug.Assert(epmInfo.IsSyndicationMapping, "Only syndication mapping is allowed for MultiValue properties.");
                        multiValueEpmInfo.SetMultiValuePropertySyndicationMapping();

                        multiValueEpmInfo.SetPropertyValuePath(pathToCurrentSegment.ToArray());

                        multiValueEpmInfo.Criteria      = epmInfo.Criteria;
                        multiValueEpmInfo.CriteriaValue = epmInfo.CriteriaValue;

                        // Now associate the current source tree segment with the new info object (or override the one from base)
                        currentSourceSegment.EpmInfo = multiValueEpmInfo;

                        // And add the new info to the target tree
                        this.epmTargetTree.Add(multiValueEpmInfo);

                        // And continue with the walk of the source path.
                        // This means that the EPM attribute specified as the input to this method is still to be added
                        // It might be added to the source tree if the path is longer (property on an item in the MultiValue property of complex types)
                        //   or it might not be added to the source tree if this segment is the last (MultiValue property of primitive types).
                        // In any case it will be added to the target tree (so even if the MultiValue property itself is mapped to the top-level element only
                        //   the items in the MultiValue property can be mapped to child element/attribute of that top-level element).
                    }
                    else
                    {
                        Debug.Assert(currentSourceSegment.EpmInfo.DefiningTypesAreEqual(epmInfo), "The condition in the surrounding if is broken.");

                        // We have already found a MultiValue property mapped from this source node.
                        // If it's on the same defining type we need to make sure that it's the same MultiValue property being mapped
                        // First verify that the mapping for the other property has the same top-level element for the MultiValue property
                        //   since we only allow properties from one MultiValue property to be mapped to the same top-level element
                        if (multiValuePropertyTargetPath != currentSourceSegment.EpmInfo.Attribute.TargetPath ||
                            epmInfo.Attribute.TargetNamespacePrefix != currentSourceSegment.EpmInfo.Attribute.TargetNamespacePrefix ||
                            epmInfo.Attribute.TargetNamespaceUri != currentSourceSegment.EpmInfo.Attribute.TargetNamespaceUri ||
                            epmInfo.Criteria != currentSourceSegment.EpmInfo.Criteria ||
                            String.Compare(epmInfo.Attribute.CriteriaValue, currentSourceSegment.EpmInfo.CriteriaValue, StringComparison.OrdinalIgnoreCase) != 0)
                        {
                            throw new ODataException(Strings.EpmSourceTree_PropertiesFromSameMultiValueMappedToDifferentTopLevelElements(currentSourceSegment.EpmInfo.Attribute.SourcePath, currentSourceSegment.EpmInfo.DefiningType.Name));
                        }

                        // Second verify that the mappings for both properties have the same KeepInContent value
                        if (epmInfo.Attribute.KeepInContent != currentSourceSegment.EpmInfo.Attribute.KeepInContent)
                        {
                            throw new ODataException(Strings.EpmSourceTree_PropertiesFromSameMultiValueMappedWithDifferentKeepInContent(currentSourceSegment.EpmInfo.Attribute.SourcePath, currentSourceSegment.EpmInfo.DefiningType.Name));
                        }
                    }
                }
            }

            // The last segment is the one being mapped from by the user specified attribute.
            // It must be a primitive type - we don't allow mappings of anything else than primitive properties directly.
            // Note that we can only verify this for non-open properties, for open properties we must assume it's a primitive type
            //   and we will make this check later during serialization again when we actually have the value of the property.
            if (currentType != null)
            {
                if (currentType.ResourceTypeKind != ResourceTypeKind.Primitive)
                {
                    throw new ODataException(Strings.EpmSourceTree_EndsWithNonPrimitiveType(currentSourceSegment.PropertyName));
                }

                SyndicationItemProperty targetSyndicationItem = epmInfo.Attribute.TargetSyndicationItem;
                if (targetSyndicationItem == SyndicationItemProperty.LinkRel || targetSyndicationItem == SyndicationItemProperty.CategoryScheme)
                {
                    if (PrimitiveStringResourceType != currentType)
                    {
                        throw new InvalidOperationException(Strings.EpmSourceTree_NonStringPropertyMappedToConditionAttribute(
                                                                currentSourceSegment.PropertyName,
                                                                epmInfo.DefiningType.FullName,
                                                                targetSyndicationItem.ToString()));
                    }
                }
            }

            if (multiValuePropertySegment == currentSourceSegment)
            {
                // If the MultiValue property is the last segment it means that the MultiValue property itself is being mapped (and it must be a MultiValue of primitive types).

                // If we found the MultiValue property already in the tree, here we actually want the item of the MultiValue property (as the MultiValue one was processed above already)
                // If we have the item value already in the tree use it as the foundProperty so that we correctly check the duplicate mappings below
                if (foundSourceSegment != null)
                {
                    Debug.Assert(foundSourceSegment == currentSourceSegment, "If we found an existing segment it must be the current one.");
                    foundSourceSegment = currentSourceSegment.SubProperties.SingleOrDefault(e => e.IsMultiValueItemValue);
                }

                if (foundSourceSegment == null)
                {
                    // This is a bit of a special case. In the source tree we will create a special node to represent the item value (we need that to be able to tell
                    //   if it was not mapped twice).
                    // In the target tree, we will also create a special node which will hold the information specific
                    //   to serialization of the item value (for example the exact syndication mapping target and so on).
                    //   The creation of the special node is done in the target tree Add method.
                    EpmSourcePathSegment newSegment = EpmSourcePathSegment.CreateMultiValueItemValueSegment();
                    currentSourceSegment.SubProperties.Add(newSegment);
                    currentSourceSegment = newSegment;
                }
                else
                {
                    currentSourceSegment = foundSourceSegment;
                }
            }

            // Note that once we're here the EpmInfo we have is never the MultiValue property itself, it's always either a non-MultiValue property
            //   or MultiValue item property.
            Debug.Assert(foundSourceSegment == null || foundSourceSegment.EpmInfo != null, "Can't have a leaf node in the tree without EpmInfo.");

            // Two EpmAttributes with same PropertyName in the same ResourceType, this could be a result of inheritance
            if (foundSourceSegment != null)
            {
                Debug.Assert(Object.ReferenceEquals(foundSourceSegment, currentSourceSegment), "currentSourceSegment variable should have been updated already to foundSourceSegment");
                Debug.Assert(
                    foundSourceSegment.EpmInfo.MultiValueStatus != EntityPropertyMappingMultiValueStatus.MultiValueProperty,
                    "We should never get here with a MultiValue property itself, we should have a node represent its item or property on the item instead.");

                // Check for duplicates on the same entity type
                Debug.Assert(foundSourceSegment.SubProperties.Count == 0, "If non-leaf, it means we allowed complex type to be a leaf node");
                if (foundSourceSegment.EpmInfo.DefiningTypesAreEqual(epmInfo))
                {
                    throw new ODataException(Strings.EpmSourceTree_DuplicateEpmAttrsWithSameSourceName(epmInfo.Attribute.SourcePath, epmInfo.DefiningType.Name));
                }

                // In case of inheritance, we need to remove the node from target tree which was mapped to base type property
                this.epmTargetTree.Remove(foundSourceSegment.EpmInfo);
            }

            epmInfo.SetPropertyValuePath(pathToCurrentSegment.ToArray());
            currentSourceSegment.EpmInfo = epmInfo;

            if (multiValuePropertySegment != null)
            {
                Debug.Assert(multiValuePropertySegment.EpmInfo != null, "All MultiValue property segments must have EpmInfo assigned.");

                // We are mapping a MultiValue property - so mark the info as a MultiValue item property (since the MultiValue property itself was added above)
                epmInfo.MultiValueStatus = EntityPropertyMappingMultiValueStatus.MultiValueItemProperty;

                // Set the item type on each of the item properties, so that the segmented path know from which type to start
                epmInfo.MultiValueItemType = multiValuePropertySegment.EpmInfo.MultiValueItemType;

                // And trim its property value path to start from the MultiValue item. This path is basically a list of properties to traverse
                //   when access the value of the property on the specified resource. For non-MultiValue and MultiValue properties themselves
                //   this path starts with the entity instance. For MultiValue item properties this path starts with the MultiValue item instance.
                //   Note that if it's a MultiValue of primitive types, the path is going to be empty meaning that the value is the item instance itself.
                epmInfo.TrimMultiValueItemPropertyPath(multiValuePropertySegment.EpmInfo);

#if DEBUG
                // Check that if the MultiValue item is of primitive type, we can only ever add a single child source segment which points directly to the MultiValue property itself
                // If we would allow this here, we would fail later, but with a much weirder error message
                Debug.Assert(
                    multiValuePropertySegment.EpmInfo.MultiValueItemType.ResourceTypeKind != ResourceTypeKind.Primitive || epmInfo.PropertyValuePath.Length == 0,
                    "We shoud have failed to map a subproperty of a primitive MultiValue item.");
#endif
            }

            this.epmTargetTree.Add(epmInfo);
        }
        /// <summary>
        /// Obtains the epm information for a single property by reading csdl content
        /// </summary>
        /// <param name="extendedProperties">Collection of extended metadata properties for a resource</param>
        /// <param name="typeName">Type for which we are reading the metadata properties</param>
        /// <param name="memberName">Member for which we are reading the metadata properties</param>
        /// <returns>EpmPropertyInformation corresponding to read metadata properties</returns>
        private static IEnumerable <EpmPropertyInformation> GetEpmPropertyInformation(IEnumerable <MetadataProperty> extendedProperties, String typeName, String memberName)
        {
            EpmAttributeNameBuilder epmAttributeNameBuilder = new EpmAttributeNameBuilder();

            while (true)
            {
                bool pathGiven = true;

                // EpmTargetPath is the only non-optional EPM attribute. If it is declared we need to take care of mapping.
                MetadataProperty epmTargetPathProperty = FindSingletonExtendedProperty(
                    extendedProperties,
                    epmAttributeNameBuilder.EpmTargetPath,
                    typeName,
                    memberName);

                if (epmTargetPathProperty != null)
                {
                    // By default, we keep the copy in content for backwards compatibility
                    bool epmKeepInContent = true;

                    MetadataProperty epmKeepInContentProperty = FindSingletonExtendedProperty(
                        extendedProperties,
                        epmAttributeNameBuilder.EpmKeepInContent,
                        typeName,
                        memberName);
                    if (epmKeepInContentProperty != null)
                    {
                        if (!Boolean.TryParse(Convert.ToString(epmKeepInContentProperty.Value, CultureInfo.InvariantCulture), out epmKeepInContent))
                        {
                            throw new InvalidOperationException(memberName == null ?
                                                                Strings.ObjectContext_InvalidValueForEpmPropertyType(epmAttributeNameBuilder.EpmKeepInContent, typeName) :
                                                                Strings.ObjectContext_InvalidValueForEpmPropertyMember(epmAttributeNameBuilder.EpmKeepInContent, memberName, typeName));
                        }
                    }

                    MetadataProperty epmSourcePathProperty = FindSingletonExtendedProperty(
                        extendedProperties,
                        epmAttributeNameBuilder.EpmSourcePath,
                        typeName,
                        memberName);
                    String epmSourcePath;
                    if (epmSourcePathProperty == null)
                    {
                        if (memberName == null)
                        {
                            throw new InvalidOperationException(Strings.ObjectContext_MissingExtendedAttributeType(epmAttributeNameBuilder.EpmSourcePath, typeName));
                        }

                        pathGiven     = false;
                        epmSourcePath = memberName;
                    }
                    else
                    {
                        epmSourcePath = Convert.ToString(epmSourcePathProperty.Value, CultureInfo.InvariantCulture);
                    }

                    String epmTargetPath = Convert.ToString(epmTargetPathProperty.Value, CultureInfo.InvariantCulture);

                    // if the property is not a sydication property MapEpmTargetPathToSyndicationProperty
                    // will return SyndicationItemProperty.CustomProperty
                    SyndicationItemProperty targetSyndicationItem = MapEpmTargetPathToSyndicationProperty(epmTargetPath);

                    MetadataProperty epmContentKindProperty = FindSingletonExtendedProperty(
                        extendedProperties,
                        epmAttributeNameBuilder.EpmContentKind,
                        typeName,
                        memberName);

                    MetadataProperty epmNsPrefixProperty = FindSingletonExtendedProperty(
                        extendedProperties,
                        epmAttributeNameBuilder.EpmNsPrefix,
                        typeName,
                        memberName);

                    MetadataProperty epmNsUriProperty = FindSingletonExtendedProperty(
                        extendedProperties,
                        epmAttributeNameBuilder.EpmNsUri,
                        typeName,
                        memberName);

                    // ContentKind is mutually exclusive with NsPrefix and NsUri properties
                    if (epmContentKindProperty != null)
                    {
                        if (epmNsPrefixProperty != null || epmNsUriProperty != null)
                        {
                            string epmPropertyName = epmNsPrefixProperty != null ? epmAttributeNameBuilder.EpmNsPrefix : epmAttributeNameBuilder.EpmNsUri;

                            throw new InvalidOperationException(memberName == null ?
                                                                Strings.ObjectContext_InvalidAttributeForNonSyndicationItemsType(epmPropertyName, typeName) :
                                                                Strings.ObjectContext_InvalidAttributeForNonSyndicationItemsMember(epmPropertyName, memberName, typeName));
                        }
                    }

                    // epmNsPrefixProperty and epmNsUriProperty can be non-null only for non-Atom mapping. Since they are optional we need to check
                    // if it was possible to map the target path to a syndication item name. if it was not (i.e. targetSyndicationItem == SyndicationItemProperty.CustomProperty)
                    // this is a non-Atom kind of mapping.
                    if (epmNsPrefixProperty != null || epmNsUriProperty != null || targetSyndicationItem == SyndicationItemProperty.CustomProperty)
                    {
                        String epmNsPrefix = epmNsPrefixProperty != null?Convert.ToString(epmNsPrefixProperty.Value, CultureInfo.InvariantCulture) : null;

                        String epmNsUri = epmNsUriProperty != null?Convert.ToString(epmNsUriProperty.Value, CultureInfo.InvariantCulture) : null;

                        yield return(new EpmPropertyInformation
                        {
                            IsAtom = false,
                            KeepInContent = epmKeepInContent,
                            SourcePath = epmSourcePath,
                            PathGiven = pathGiven,
                            TargetPath = epmTargetPath,
                            NsPrefix = epmNsPrefix,
                            NsUri = epmNsUri
                        });
                    }
                    else
                    {
                        SyndicationTextContentKind syndicationContentKind;

                        if (epmContentKindProperty != null)
                        {
                            syndicationContentKind = MapEpmContentKindToSyndicationTextContentKind(
                                Convert.ToString(epmContentKindProperty.Value, CultureInfo.InvariantCulture),
                                typeName,
                                memberName);
                        }
                        else
                        {
                            syndicationContentKind = SyndicationTextContentKind.Plaintext;
                        }

                        yield return(new EpmPropertyInformation
                        {
                            IsAtom = true,
                            KeepInContent = epmKeepInContent,
                            SourcePath = epmSourcePath,
                            PathGiven = pathGiven,
                            SyndicationItem = targetSyndicationItem,
                            ContentKind = syndicationContentKind
                        });
                    }

                    epmAttributeNameBuilder.MoveNext();
                }
                else
                {
                    yield break;
                }
            }
        }
Пример #27
0
 /// <summary>
 /// Converts test enum SyndicationItemProperty to product enum.
 /// </summary>
 /// <param name="item">test enum value</param>
 /// <returns>product enum</returns>
 public static AtomSyndicationItemProperty ToProductEnum(this SyndicationItemProperty item)
 {
     return(ConvertEnum <SyndicationItemProperty, AtomSyndicationItemProperty>(item));
 }
        /// <summary>
        /// Maps the enumeration of allowed <see cref="SyndicationItemProperty"/> values to their string representations.
        /// </summary>
        /// <param name="targetSyndicationItem">Value of the <see cref="SyndicationItemProperty"/> given in 
        /// the <see cref="EntityPropertyMappingAttribute"/> contstructor.</param>
        /// <returns>String representing the xml element path in the syndication property.</returns>
        internal static String SyndicationItemPropertyToPath(SyndicationItemProperty targetSyndicationItem)
        {
            DebugUtils.CheckNoExternalCallers();

            switch (targetSyndicationItem)
            {
                case SyndicationItemProperty.AuthorEmail:
                    return "author/email";
                case SyndicationItemProperty.AuthorName:
                    return "author/name";
                case SyndicationItemProperty.AuthorUri:
                    return "author/uri";
                case SyndicationItemProperty.ContributorEmail:
                    return "contributor/email";
                case SyndicationItemProperty.ContributorName:
                    return "contributor/name";
                case SyndicationItemProperty.ContributorUri:
                    return "contributor/uri";
                case SyndicationItemProperty.Updated:
                    return "updated";
                case SyndicationItemProperty.Published:
                    return "published";
                case SyndicationItemProperty.Rights:
                    return "rights";
                case SyndicationItemProperty.Summary:
                    return "summary";
                case SyndicationItemProperty.Title:
                    return "title";
                case SyndicationItemProperty.CategoryLabel:
                    return "category/@label";
                case SyndicationItemProperty.CategoryScheme:
                    return "category/@scheme";
                case SyndicationItemProperty.CategoryTerm:
                    return "category/@term";
                case SyndicationItemProperty.LinkHref:
                    return "link/@href";
                case SyndicationItemProperty.LinkHrefLang:
                    return "link/@hreflang";
                case SyndicationItemProperty.LinkLength:
                    return "link/@length";
                case SyndicationItemProperty.LinkRel:
                    return "link/@rel";
                case SyndicationItemProperty.LinkTitle:
                    return "link/@title";
                case SyndicationItemProperty.LinkType:
                    return "link/@type";
                default:
                    throw new ArgumentException(Strings.EntityPropertyMapping_EpmAttribute("targetSyndicationItem"));
            }
        }
Пример #29
0
        private static IEnumerable <EpmPropertyInformation> GetEpmPropertyInformation(MetadataItem metadataItem, string typeName, string memberName)
        {
            EpmAttributeNameBuilder iteratorVariable0 = new EpmAttributeNameBuilder();

            while (true)
            {
                string           iteratorVariable6;
                bool             iteratorVariable1 = true;
                MetadataProperty iteratorVariable2 = EdmUtil.FindExtendedProperty(metadataItem, iteratorVariable0.EpmTargetPath);
                if (iteratorVariable2 == null)
                {
                    break;
                }
                bool             result            = true;
                MetadataProperty iteratorVariable4 = EdmUtil.FindExtendedProperty(metadataItem, iteratorVariable0.EpmKeepInContent);
                if ((iteratorVariable4 != null) && !bool.TryParse(Convert.ToString(iteratorVariable4.Value, CultureInfo.InvariantCulture), out result))
                {
                    throw new InvalidOperationException((memberName == null) ? Strings.ObjectContext_InvalidValueForEpmPropertyType(iteratorVariable0.EpmKeepInContent, typeName) : Strings.ObjectContext_InvalidValueForEpmPropertyMember(iteratorVariable0.EpmKeepInContent, memberName, typeName));
                }
                MetadataProperty iteratorVariable5 = EdmUtil.FindExtendedProperty(metadataItem, iteratorVariable0.EpmSourcePath);
                if (iteratorVariable5 == null)
                {
                    if (memberName == null)
                    {
                        throw new InvalidOperationException(Strings.ObjectContext_MissingExtendedAttributeType(iteratorVariable0.EpmSourcePath, typeName));
                    }
                    iteratorVariable1 = false;
                    iteratorVariable6 = memberName;
                }
                else
                {
                    iteratorVariable6 = Convert.ToString(iteratorVariable5.Value, CultureInfo.InvariantCulture);
                }
                string targetPath = Convert.ToString(iteratorVariable2.Value, CultureInfo.InvariantCulture);
                SyndicationItemProperty iteratorVariable8  = EpmTranslate.MapEpmTargetPathToSyndicationProperty(targetPath);
                MetadataProperty        iteratorVariable9  = EdmUtil.FindExtendedProperty(metadataItem, iteratorVariable0.EpmContentKind);
                MetadataProperty        iteratorVariable10 = EdmUtil.FindExtendedProperty(metadataItem, iteratorVariable0.EpmNsPrefix);
                MetadataProperty        iteratorVariable11 = EdmUtil.FindExtendedProperty(metadataItem, iteratorVariable0.EpmNsUri);
                if ((iteratorVariable9 != null) && ((iteratorVariable10 != null) || (iteratorVariable11 != null)))
                {
                    string str = (iteratorVariable10 != null) ? iteratorVariable0.EpmNsPrefix : iteratorVariable0.EpmNsUri;
                    throw new InvalidOperationException((memberName == null) ? Strings.ObjectContext_InvalidAttributeForNonSyndicationItemsType(str, typeName) : Strings.ObjectContext_InvalidAttributeForNonSyndicationItemsMember(str, memberName, typeName));
                }
                if (((iteratorVariable10 != null) || (iteratorVariable11 != null)) || (iteratorVariable8 == SyndicationItemProperty.CustomProperty))
                {
                    string iteratorVariable12 = (iteratorVariable10 != null) ? Convert.ToString(iteratorVariable10.Value, CultureInfo.InvariantCulture) : null;
                    string iteratorVariable13 = (iteratorVariable11 != null) ? Convert.ToString(iteratorVariable11.Value, CultureInfo.InvariantCulture) : null;
                    EpmPropertyInformation iteratorVariable14 = new EpmPropertyInformation {
                        IsAtom        = false,
                        KeepInContent = result,
                        SourcePath    = iteratorVariable6,
                        PathGiven     = iteratorVariable1,
                        TargetPath    = targetPath,
                        NsPrefix      = iteratorVariable12,
                        NsUri         = iteratorVariable13
                    };
                    yield return(iteratorVariable14);
                }
                else
                {
                    SyndicationTextContentKind plaintext;
                    if (iteratorVariable9 != null)
                    {
                        plaintext = EpmTranslate.MapEpmContentKindToSyndicationTextContentKind(Convert.ToString(iteratorVariable9.Value, CultureInfo.InvariantCulture), typeName, memberName);
                    }
                    else
                    {
                        plaintext = SyndicationTextContentKind.Plaintext;
                    }
                    EpmPropertyInformation iteratorVariable16 = new EpmPropertyInformation {
                        IsAtom          = true,
                        KeepInContent   = result,
                        SourcePath      = iteratorVariable6,
                        PathGiven       = iteratorVariable1,
                        SyndicationItem = iteratorVariable8,
                        ContentKind     = plaintext
                    };
                    yield return(iteratorVariable16);
                }
                iteratorVariable0.MoveNext();
            }
        }
Пример #30
0
        /// <summary>
        /// Given an object returns the corresponding DateTimeOffset value through conversions.
        /// </summary>
        /// <param name="propertyValue">Object containing property value.</param>
        /// <param name="targetProperty">The target syndication property for the mapping (used for exception messages).</param>
        /// <param name="version">The version of the OData protocol to use.</param>
        /// <returns>DateTimeOffset after conversion.</returns>
        private static DateTimeOffset CreateDateTimeValue(object propertyValue, SyndicationItemProperty targetProperty, ODataVersion version)
        {
            if (propertyValue == null)
            {
                // In V3 we are to use m:null extension attribute to mark null values. Due to that we need to fail
                // because syndication API doesn't allow us to put extension attributes on publish or updated ATOM elements 
                // (even though the spec allows it) and the product used syndication APIs. In future version of the protocol we might be able
                // to lift the restriction, but for now we have to keep this for backward compat.
                if (version >= ODataVersion.V3)
                {
                    throw new ODataException(Strings.EpmSyndicationWriter_DateTimePropertyHasNullValue(targetProperty.ToString()));
                }
                else
                {
                    return DateTimeOffset.Now;
                }
            }

            if (propertyValue is DateTimeOffset)
            {
                return (DateTimeOffset)propertyValue;
            }
            else if (propertyValue is DateTime)
            {
                // DateTimeOffset takes care of DateTimes of Unspecified kind so we won't end up 
                // with datetime without timezone info mapped to atom:updated or atom:published element.
                return new DateTimeOffset((DateTime)propertyValue);
            }

            string stringValue = propertyValue as string;
            if (stringValue != null)
            {
                DateTimeOffset date;
                if (!DateTimeOffset.TryParse(stringValue, out date))
                {
                    DateTime result;
                    if (!DateTime.TryParse(stringValue, out result))
                    {
                        throw new ODataException(Strings.EpmSyndicationWriter_DateTimePropertyCanNotBeConverted(targetProperty.ToString()));
                    }

                    return new DateTimeOffset(result);
                }

                return date;
            }
            else
            {
                try
                {
                    return new DateTimeOffset(Convert.ToDateTime(propertyValue, CultureInfo.InvariantCulture));
                }
                catch (Exception e)
                {
                    if (!ExceptionUtils.IsCatchableExceptionType(e))
                    {
                        throw;
                    }

                    throw new ODataException(Strings.EpmSyndicationWriter_DateTimePropertyCanNotBeConverted(targetProperty.ToString()));
                }
            }
        }
Пример #31
0
        /// <summary>
        /// Given an object returns the corresponding DateTimeOffset value through conversions.
        /// </summary>
        /// <param name="propertyValue">Object containing property value.</param>
        /// <param name="targetProperty">The target syndication property for the mapping (used for exception messages).</param>
        /// <param name="version">The version of the OData protocol to use.</param>
        /// <returns>DateTimeOffset after conversion.</returns>
        private static DateTimeOffset CreateDateTimeValue(object propertyValue, SyndicationItemProperty targetProperty, ODataVersion version)
        {
            if (propertyValue == null)
            {
                // In V3 we are to use m:null extension attribute to mark null values. Due to that we need to fail
                // because syndication API doesn't allow us to put extension attributes on publish or updated ATOM elements
                // (even though the spec allows it) and the product used syndication APIs. In future version of the protocol we might be able
                // to lift the restriction, but for now we have to keep this for backward compat.
                if (version >= ODataVersion.V3)
                {
                    throw new ODataException(Strings.EpmSyndicationWriter_DateTimePropertyHasNullValue(targetProperty.ToString()));
                }
                else
                {
                    return(DateTimeOffset.Now);
                }
            }

            if (propertyValue is DateTimeOffset)
            {
                return((DateTimeOffset)propertyValue);
            }
            else if (propertyValue is DateTime)
            {
                // DateTimeOffset takes care of DateTimes of Unspecified kind so we won't end up
                // with datetime without timezone info mapped to atom:updated or atom:published element.
                return(new DateTimeOffset((DateTime)propertyValue));
            }

            string stringValue = propertyValue as string;

            if (stringValue != null)
            {
                DateTimeOffset date;
                if (!DateTimeOffset.TryParse(stringValue, out date))
                {
                    DateTime result;
                    if (!DateTime.TryParse(stringValue, out result))
                    {
                        throw new ODataException(Strings.EpmSyndicationWriter_DateTimePropertyCanNotBeConverted(targetProperty.ToString()));
                    }

                    return(new DateTimeOffset(result));
                }

                return(date);
            }
            else
            {
                try
                {
                    return(new DateTimeOffset(Convert.ToDateTime(propertyValue, CultureInfo.InvariantCulture)));
                }
                catch (Exception e)
                {
                    if (!ExceptionUtils.IsCatchableExceptionType(e))
                    {
                        throw;
                    }

                    throw new ODataException(Strings.EpmSyndicationWriter_DateTimePropertyCanNotBeConverted(targetProperty.ToString()));
                }
            }
        }
Пример #32
0
 internal static string MapSyndicationPropertyToEpmTargetPath(SyndicationItemProperty property)
 {
     return(syndicationItemToTargetPath[(int)property]);
 }
        /// <summary>
        /// Maps the enumeration of allowed <see cref="SyndicationItemProperty"/> values to their string representations.
        /// </summary>
        /// <param name="targetSyndicationItem">Value of the <see cref="SyndicationItemProperty"/> given in
        /// the <see cref="EntityPropertyMappingAttribute"/> contstructor.</param>
        /// <returns>String representing the xml element path in the syndication property.</returns>
        internal static String SyndicationItemPropertyToPath(SyndicationItemProperty targetSyndicationItem)
        {
            DebugUtils.CheckNoExternalCallers();

            switch (targetSyndicationItem)
            {
            case SyndicationItemProperty.AuthorEmail:
                return("author/email");

            case SyndicationItemProperty.AuthorName:
                return("author/name");

            case SyndicationItemProperty.AuthorUri:
                return("author/uri");

            case SyndicationItemProperty.ContributorEmail:
                return("contributor/email");

            case SyndicationItemProperty.ContributorName:
                return("contributor/name");

            case SyndicationItemProperty.ContributorUri:
                return("contributor/uri");

            case SyndicationItemProperty.Updated:
                return("updated");

            case SyndicationItemProperty.Published:
                return("published");

            case SyndicationItemProperty.Rights:
                return("rights");

            case SyndicationItemProperty.Summary:
                return("summary");

            case SyndicationItemProperty.Title:
                return("title");

            case SyndicationItemProperty.CategoryLabel:
                return("category/@label");

            case SyndicationItemProperty.CategoryScheme:
                return("category/@scheme");

            case SyndicationItemProperty.CategoryTerm:
                return("category/@term");

            case SyndicationItemProperty.LinkHref:
                return("link/@href");

            case SyndicationItemProperty.LinkHrefLang:
                return("link/@hreflang");

            case SyndicationItemProperty.LinkLength:
                return("link/@length");

            case SyndicationItemProperty.LinkRel:
                return("link/@rel");

            case SyndicationItemProperty.LinkTitle:
                return("link/@title");

            case SyndicationItemProperty.LinkType:
                return("link/@type");

            default:
                throw new ArgumentException(Strings.EntityPropertyMapping_EpmAttribute("targetSyndicationItem"));
            }
        }
        /// <summary>
        /// Set a property of atom:contributor element. atom:contributor is created if does not exist.
        /// </summary>
        /// <param name="propertyToSet">Property to be set.</param>
        /// <param name="textPropertyValue">Value of the property.</param>
        private void SetContributorProperty(SyndicationItemProperty propertyToSet, string textPropertyValue)
        {
            if (this.Target.Contributors.Count == 0) 
            {
                this.Target.Contributors.Add(new SyndicationPerson());
            }

            // We can have at most one contributor
            switch (propertyToSet) 
            {
                case SyndicationItemProperty.ContributorEmail:
                    this.Target.Contributors[0].Email = textPropertyValue;
                    break;
                case SyndicationItemProperty.ContributorName:
                    this.Target.Contributors[0].Name = textPropertyValue;
                    break;
                case SyndicationItemProperty.ContributorUri:
                    this.Target.Contributors[0].Uri = textPropertyValue;
                    break;
                default:
                    Debug.Fail("propertyToSet is not a Contributor property.");
                    break;
            }

            Debug.Assert(this.Target.Contributors.Count == 1, "There should be one and only one contributor.");
        }
Пример #35
0
        private static DateTimeOffset CreateDateTimeValue(object propertyValue, SyndicationItemProperty targetProperty, ODataWriterBehavior writerBehavior)
        {
            Debug.Assert(
                writerBehavior.FormatBehaviorKind != ODataBehaviorKind.WcfDataServicesClient,
                "CreateDateTimeValue should not be used in WCF DS client mode.");

            if (propertyValue == null)
            {
                return DateTimeOffset.Now;
            }

            if (propertyValue is DateTimeOffset)
            {
                return (DateTimeOffset)propertyValue;
            }

            if (propertyValue is DateTime)
            {
                // DateTimeOffset takes care of DateTimes of Unspecified kind so we won't end up 
                // with datetime without timezone info mapped to atom:updated or atom:published element.
                return new DateTimeOffset((DateTime)propertyValue);
            }

            string stringValue = propertyValue as string;
            if (stringValue != null)
            {
                DateTimeOffset date;
                if (!DateTimeOffset.TryParse(stringValue, out date))
                {
                    DateTime result;
                    if (!DateTime.TryParse(stringValue, out result))
                    {
                        throw new ODataException(o.Strings.EpmSyndicationWriter_DateTimePropertyCanNotBeConverted(targetProperty.ToString()));
                    }

                    return new DateTimeOffset(result);
                }

                return date;
            }

            try
            {
                return new DateTimeOffset(Convert.ToDateTime(propertyValue, CultureInfo.InvariantCulture));
            }
            catch (Exception e)
            {
                if (!ExceptionUtils.IsCatchableExceptionType(e))
                {
                    throw;
                }

                throw new ODataException(o.Strings.EpmSyndicationWriter_DateTimePropertyCanNotBeConverted(targetProperty.ToString()));
            }
        }
        /// <summary>
        /// Used for conditional mapping to atom:link[@href] and atom:category[@term].
        /// </summary>
        /// <param name="sourcePath">Source property path.</param>
        /// <param name="targetSyndicationItem">Syndication item to which the <see cref="sourcePath"/> is mapped.</param>
        /// <param name="keepInContent">If true the property value is kept in the content section as before, 
        /// when false the property value is only placed at the mapped location.</param>
        /// <param name="criteriaValue">Criteria value that is used as a condition.</param>
        public EntityPropertyMappingAttribute(String sourcePath, SyndicationItemProperty targetSyndicationItem, bool keepInContent, String criteriaValue)
        {
            if (String.IsNullOrEmpty(sourcePath))
            {
                throw new ArgumentException(Strings.EntityPropertyMapping_EpmAttribute("sourcePath"));
            }

            this.sourcePath = sourcePath;

            if (String.IsNullOrEmpty(criteriaValue))
            {
                throw new ArgumentException(Strings.EntityPropertyMapping_EpmAttribute("criteriaValue"));
            }

            this.criteriaValue = criteriaValue;
            this.targetPath = SyndicationItemPropertyToPath(targetSyndicationItem);
            this.targetSyndicationItem = targetSyndicationItem;
            this.targetTextContentKind = SyndicationTextContentKind.Plaintext;
            this.targetNamespacePrefix = AtomConstants.NonEmptyAtomNamespacePrefix;
            this.targetNamespaceUri = AtomConstants.AtomNamespace;
            this.keepInContent = keepInContent;
        }