/// <summary> /// By going over EntityPropertyMappingInfoAttribute(s) defined on <paramref name="type"/> /// builds the corresponding EntityPropertyMappingInfo /// </summary> /// <param name="type">Type being looked at</param> /// <param name="clientTypeAnnotation">The ClientTypeAnnotation to refer to</param> /// <param name="sourceTree">The source tree to populate.</param> private static void BuildEpmInfo(Type type, ClientTypeAnnotation clientTypeAnnotation, System.Data.Services.Client.Serializers.EpmSourceTree sourceTree) { // EPM is only allowed on entity types. Note that we can't throw now if the EPM attribute is on a complex type since we didn't throw when we ship V2. if (clientTypeAnnotation.IsEntityType) { Type baseType = c.PlatformHelper.GetBaseType(type); ClientTypeAnnotation baseClientTypeAnnotation = null; ClientEdmModel clientEdmModel = clientTypeAnnotation.model; ODataEntityPropertyMappingCollection mappings = null; if (baseType != null && baseType != typeof(object)) { // have CLR base type if (((EdmStructuredType)clientTypeAnnotation.EdmType).BaseType == null) { // CLR base type is not an entity type - append its EPM onto the current type annotation BuildEpmInfo(baseType, clientTypeAnnotation, sourceTree); // we should not create a new mapping in this case mappings = clientEdmModel.GetAnnotationValue <ODataEntityPropertyMappingCollection>(clientTypeAnnotation.EdmType); } else { // CLR base type is an entity type, build EPM onto the base type annotation baseClientTypeAnnotation = clientEdmModel.GetClientTypeAnnotation(baseType); BuildEpmInfo(baseType, baseClientTypeAnnotation, sourceTree); } } foreach (EntityPropertyMappingAttribute epmAttr in type.GetCustomAttributes(typeof(EntityPropertyMappingAttribute), false)) { BuildEpmInfo(epmAttr, type, clientTypeAnnotation, sourceTree); // Add these mappings to the ODataEntityPropertyMapping class so that // ODataLib can consume them if (mappings == null) { mappings = new ODataEntityPropertyMappingCollection(); } mappings.Add(epmAttr); } if (mappings != null) { ODataEntityPropertyMappingCollection oldMappings = clientEdmModel.GetAnnotationValue <ODataEntityPropertyMappingCollection>(clientTypeAnnotation.EdmType); if (oldMappings != null) { List <EntityPropertyMappingAttribute> exclusiveMappings = oldMappings.Where(oldM => !mappings.Any(newM => oldM.SourcePath == newM.SourcePath)).ToList(); foreach (EntityPropertyMappingAttribute epmAttr in exclusiveMappings) { mappings.Add(epmAttr); } } clientEdmModel.SetAnnotationValue(clientTypeAnnotation.EdmType, mappings); } } }
internal bool IsDirty(ODataEntityPropertyMappingCollection propertyMappings) { if ((this.mappings == null) && (propertyMappings == null)) { return false; } return (!object.ReferenceEquals(this.mappings, propertyMappings) || (this.mappings.Count != propertyMappings.Count)); }
internal ODataEntityPropertyMappingCache(ODataEntityPropertyMappingCollection mappings, IEdmModel model, int totalMappingCount) { this.mappings = mappings; this.model = model; this.totalMappingCount = totalMappingCount; this.mappingsForInheritedProperties = new List<EntityPropertyMappingAttribute>(); this.mappingsForDeclaredProperties = (mappings == null) ? new List<EntityPropertyMappingAttribute>() : new List<EntityPropertyMappingAttribute>(mappings); this.epmTargetTree = new Microsoft.Data.OData.Metadata.EpmTargetTree(); this.epmSourceTree = new Microsoft.Data.OData.Metadata.EpmSourceTree(this.epmTargetTree); }
internal static void ConvertEntityPropertyMappings(MetadataProviderEdmModel model, ResourceType resourceType, EdmEntityType entityType) { IEnumerable <EntityPropertyMappingAttribute> allEpmInfo = resourceType.AllEpmInfo; if (allEpmInfo != null) { ODataEntityPropertyMappingCollection mappings = new ODataEntityPropertyMappingCollection(); foreach (EntityPropertyMappingAttribute attribute in allEpmInfo) { mappings.Add(attribute); } model.SetAnnotationValue <ODataEntityPropertyMappingCollection>(entityType, mappings); } }
private static void BuildEpmInfo(Type type, ClientTypeAnnotation clientTypeAnnotation, System.Data.Services.Client.Serializers.EpmSourceTree sourceTree) { if (clientTypeAnnotation.IsEntityType) { Func <EntityPropertyMappingAttribute, bool> predicate = null; Type baseType = type.BaseType; ClientTypeAnnotation annotation = null; ClientEdmModel model = ClientEdmModel.GetModel(clientTypeAnnotation.MaxProtocolVersion); ODataEntityPropertyMappingCollection mappings = null; if ((baseType != null) && (baseType != typeof(object))) { if (((EdmStructuredType)clientTypeAnnotation.EdmType).BaseType == null) { BuildEpmInfo(baseType, clientTypeAnnotation, sourceTree); mappings = model.GetAnnotationValue <ODataEntityPropertyMappingCollection>(clientTypeAnnotation.EdmType); } else { annotation = model.GetClientTypeAnnotation(baseType); BuildEpmInfo(baseType, annotation, sourceTree); } } foreach (EntityPropertyMappingAttribute attribute in type.GetCustomAttributes(typeof(EntityPropertyMappingAttribute), false)) { BuildEpmInfo(attribute, type, clientTypeAnnotation, sourceTree); if (mappings == null) { mappings = new ODataEntityPropertyMappingCollection(); } mappings.Add(attribute); } if (mappings != null) { ODataEntityPropertyMappingCollection annotationValue = model.GetAnnotationValue <ODataEntityPropertyMappingCollection>(clientTypeAnnotation.EdmType); if (annotationValue != null) { if (predicate == null) { predicate = oldM => !mappings.Any <EntityPropertyMappingAttribute>(newM => (oldM.SourcePath == newM.SourcePath)); } foreach (EntityPropertyMappingAttribute attribute2 in annotationValue.Where <EntityPropertyMappingAttribute>(predicate).ToList <EntityPropertyMappingAttribute>()) { mappings.Add(attribute2); } } model.SetAnnotationValue <ODataEntityPropertyMappingCollection>(clientTypeAnnotation.EdmType, mappings); } } }
/// <summary> /// Constructor. /// </summary> /// <param name="mappings">The EPM mappings to create the cache for.</param> /// <param name="model">The EDM model.</param> /// <param name="totalMappingCount">The total number of entity property mappings /// for the entity type that this cache is created for (on the type itself and all its base types).</param> internal ODataEntityPropertyMappingCache(ODataEntityPropertyMappingCollection mappings, IEdmModel model, int totalMappingCount) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(model.IsUserModel(), "model.IsUserModel()"); this.mappings = mappings; this.model = model; this.totalMappingCount = totalMappingCount; // Note that we new up everything here eagerly because we will only create the EPM annotation for types // for which we know for sure that they have EPM and thus we will need all of these anyway. this.mappingsForInheritedProperties = new List<EntityPropertyMappingAttribute>(); this.mappingsForDeclaredProperties = mappings == null ? new List<EntityPropertyMappingAttribute>() : new List<EntityPropertyMappingAttribute>(mappings); this.epmTargetTree = new EpmTargetTree(); this.epmSourceTree = new EpmSourceTree(this.epmTargetTree); }
private static void BuildEpmInfo(Type type, ClientTypeAnnotation clientTypeAnnotation, System.Data.Services.Client.Serializers.EpmSourceTree sourceTree) { if (clientTypeAnnotation.IsEntityType) { Func<EntityPropertyMappingAttribute, bool> predicate = null; Type baseType = type.BaseType; ClientTypeAnnotation annotation = null; ClientEdmModel model = ClientEdmModel.GetModel(clientTypeAnnotation.MaxProtocolVersion); ODataEntityPropertyMappingCollection mappings = null; if ((baseType != null) && (baseType != typeof(object))) { if (((EdmStructuredType) clientTypeAnnotation.EdmType).BaseType == null) { BuildEpmInfo(baseType, clientTypeAnnotation, sourceTree); mappings = model.GetAnnotationValue<ODataEntityPropertyMappingCollection>(clientTypeAnnotation.EdmType); } else { annotation = model.GetClientTypeAnnotation(baseType); BuildEpmInfo(baseType, annotation, sourceTree); } } foreach (EntityPropertyMappingAttribute attribute in type.GetCustomAttributes(typeof(EntityPropertyMappingAttribute), false)) { BuildEpmInfo(attribute, type, clientTypeAnnotation, sourceTree); if (mappings == null) { mappings = new ODataEntityPropertyMappingCollection(); } mappings.Add(attribute); } if (mappings != null) { ODataEntityPropertyMappingCollection annotationValue = model.GetAnnotationValue<ODataEntityPropertyMappingCollection>(clientTypeAnnotation.EdmType); if (annotationValue != null) { if (predicate == null) { predicate = oldM => !mappings.Any<EntityPropertyMappingAttribute>(newM => (oldM.SourcePath == newM.SourcePath)); } foreach (EntityPropertyMappingAttribute attribute2 in annotationValue.Where<EntityPropertyMappingAttribute>(predicate).ToList<EntityPropertyMappingAttribute>()) { mappings.Add(attribute2); } } model.SetAnnotationValue<ODataEntityPropertyMappingCollection>(clientTypeAnnotation.EdmType, mappings); } } }
/// <summary> /// Loads the serializable EPM annotations on the given <paramref name="annotatable"/> into their in-memory representation. /// </summary> /// <param name="model">The model the annotatable belongs to.</param> /// <param name="annotatable">The <see cref="IEdmElement"/> to load the EPM annotations for.</param> /// <param name="mappings">The collection of EPM annotations to add newly loaded annotations to.</param> /// <param name="typeName">The name of the type for which to load the annotations or that declares the <paramref name="property"/>. Only used in error messages.</param> /// <param name="property">The property to parse the EPM annotations for.</param> private static void LoadEpmAnnotations(this IEdmModel model, IEdmElement annotatable, ODataEntityPropertyMappingCollection mappings, string typeName, IEdmProperty property) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(model != null, "model != null"); Debug.Assert(annotatable != null, "annotatable != null"); Debug.Assert(mappings != null, "mappings != null"); Debug.Assert(!string.IsNullOrEmpty(typeName), "!string.IsNullOrEmpty(typeName)"); IEnumerable<EpmAnnotationValues> allAnnotationValues = ParseSerializableEpmAnnotations(model, annotatable, typeName, property); if (allAnnotationValues != null) { foreach (EpmAnnotationValues annotationValues in allAnnotationValues) { // check whether we found a valid EPM configuration EntityPropertyMappingAttribute mapping = ValidateAnnotationValues(annotationValues, typeName, property); mappings.Add(mapping); } } }
/// <summary> /// Loads the serializable EPM annotations on the given <paramref name="entityType"/> into their in-memory representation. /// </summary> /// <param name="model">The model the entity type belongs to.</param> /// <param name="entityType">The <see cref="IEdmEntityType"/> to load the EPM annotations for.</param> private static void LoadEpmAnnotations(IEdmModel model, IEdmEntityType entityType) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(entityType != null, "entityType != null"); string entityTypeName = entityType.ODataFullName(); ODataEntityPropertyMappingCollection mappings = new ODataEntityPropertyMappingCollection(); // Load the annotations from the type (these are the mappings for properties not explicitly declared on this type) model.LoadEpmAnnotations(entityType, mappings, entityTypeName, null /*property*/); IEnumerable<IEdmProperty> declaredProperties = entityType.DeclaredProperties; if (declaredProperties != null) { foreach (IEdmProperty property in declaredProperties) { // Load the EPM annotations for all properties independent of their kind in order to fail on invalid property kinds. model.LoadEpmAnnotations(property, mappings, entityTypeName, property); } } // Set the new EPM annotation on the entity type only at the very end to not leave a // inconsistent annotation if building it fails. model.SetAnnotationValue(entityType, mappings); }
internal static int ValidateTotalEntityPropertyMappingCount(ODataEntityPropertyMappingCache baseCache, ODataEntityPropertyMappingCollection mappings, int maxMappingCount) { int num = (baseCache == null) ? 0 : baseCache.TotalMappingCount; int num2 = (mappings == null) ? 0 : mappings.Count; int num3 = num + num2; if (num3 > maxMappingCount) { throw new ODataException(Microsoft.Data.OData.Strings.ValidationUtils_MaxNumberOfEntityPropertyMappingsExceeded(num3, maxMappingCount)); } return num3; }
internal static int ValidateTotalEntityPropertyMappingCount(ODataEntityPropertyMappingCache baseCache, ODataEntityPropertyMappingCollection mappings, int maxMappingCount) { int num = (baseCache == null) ? 0 : baseCache.TotalMappingCount; int num2 = (mappings == null) ? 0 : mappings.Count; int num3 = num + num2; if (num3 > maxMappingCount) { throw new ODataException(Microsoft.Data.OData.Strings.ValidationUtils_MaxNumberOfEntityPropertyMappingsExceeded(num3, maxMappingCount)); } return(num3); }
private static void LoadEpmAnnotations(this IEdmModel model, IEdmElement annotatable, ODataEntityPropertyMappingCollection mappings, string typeName, IEdmProperty property) { IEnumerable<EpmAnnotationValues> enumerable = model.ParseSerializableEpmAnnotations(annotatable, typeName, property); if (enumerable != null) { foreach (EpmAnnotationValues values in enumerable) { EntityPropertyMappingAttribute mapping = ValidateAnnotationValues(values, typeName, property); mappings.Add(mapping); } } }
private static void LoadEpmAnnotations(IEdmModel model, IEdmEntityType entityType) { string typeName = entityType.ODataFullName(); ODataEntityPropertyMappingCollection mappings = new ODataEntityPropertyMappingCollection(); model.LoadEpmAnnotations(entityType, mappings, typeName, null); IEnumerable<IEdmProperty> declaredProperties = entityType.DeclaredProperties; if (declaredProperties != null) { foreach (IEdmProperty property in declaredProperties) { model.LoadEpmAnnotations(property, mappings, typeName, property); } } model.SetAnnotationValue<ODataEntityPropertyMappingCollection>(entityType, mappings); }
/// <summary> /// Validates that the total number of entity property mapping attributes on the base entity type and the current /// entity type does not exceed the specified security limit. /// </summary> /// <param name="baseCache">The EPM cache of the base entity type or null if no base entity type exists.</param> /// <param name="mappings">The EPM collection of the current entity type.</param> /// <param name="maxMappingCount">The maximum number of mappings allowed for an entity type (on the type itself and all its base types).</param> /// <returns>The total number of entity property mappings for the current entity type.</returns> internal static int ValidateTotalEntityPropertyMappingCount(ODataEntityPropertyMappingCache baseCache, ODataEntityPropertyMappingCollection mappings, int maxMappingCount) { DebugUtils.CheckNoExternalCallers(); int countOfMappingsOnBaseTypes = baseCache == null ? 0 : baseCache.TotalMappingCount; int countOfMappingsOnCurrentType = mappings == null ? 0 : mappings.Count; int totalMappingCount = countOfMappingsOnBaseTypes + countOfMappingsOnCurrentType; if (totalMappingCount > maxMappingCount) { throw new ODataException(Strings.ValidationUtils_MaxNumberOfEntityPropertyMappingsExceeded(totalMappingCount, maxMappingCount)); } return(totalMappingCount); }
/// <summary> /// Validates that the total number of entity property mapping attributes on the base entity type and the current /// entity type does not exceed the specified security limit. /// </summary> /// <param name="baseCache">The EPM cache of the base entity type or null if no base entity type exists.</param> /// <param name="mappings">The EPM collection of the current entity type.</param> /// <param name="maxMappingCount">The maximum number of mappings allowed for an entity type (on the type itself and all its base types).</param> /// <returns>The total number of entity property mappings for the current entity type.</returns> internal static int ValidateTotalEntityPropertyMappingCount(ODataEntityPropertyMappingCache baseCache, ODataEntityPropertyMappingCollection mappings, int maxMappingCount) { DebugUtils.CheckNoExternalCallers(); int countOfMappingsOnBaseTypes = baseCache == null ? 0 : baseCache.TotalMappingCount; int countOfMappingsOnCurrentType = mappings == null ? 0 : mappings.Count; int totalMappingCount = countOfMappingsOnBaseTypes + countOfMappingsOnCurrentType; if (totalMappingCount > maxMappingCount) { throw new ODataException(Strings.ValidationUtils_MaxNumberOfEntityPropertyMappingsExceeded(totalMappingCount, maxMappingCount)); } return totalMappingCount; }
/// <summary> /// Checks whether the current cache is dirty with respect to the <paramref name="propertyMappings"/>. /// </summary> /// <param name="propertyMappings">The EPM mappings to check this cache against.</param> /// <returns>true if the <paramref name="propertyMappings"/> are not the same as the ones the cache has been created for (or have changed).</returns> internal bool IsDirty(ODataEntityPropertyMappingCollection propertyMappings) { DebugUtils.CheckNoExternalCallers(); // NOTE: we only allow adding more mappings to an existing collection; so if the // references of the collections are the same and the counts are the same there has been no change. if (this.mappings == null && propertyMappings == null) { return false; } if (!object.ReferenceEquals(this.mappings, propertyMappings)) { return true; } return this.mappings.Count != propertyMappings.Count; }