private bool ShouldWritePropertyInContent(IEdmStructuredType owningType, ProjectedPropertiesAnnotation projectedProperties, string propertyName, object propertyValue, EpmSourcePathSegment epmSourcePathSegment) { bool flag = !projectedProperties.ShouldSkipProperty(propertyName); if ((((base.MessageWriterSettings.WriterBehavior != null) && base.MessageWriterSettings.WriterBehavior.UseV1ProviderBehavior) && (owningType != null)) && owningType.IsODataComplexTypeKind()) { IEdmComplexType complexType = (IEdmComplexType) owningType; CachedPrimitiveKeepInContentAnnotation annotation = base.Model.EpmCachedKeepPrimitiveInContent(complexType); if ((annotation != null) && annotation.IsKeptInContent(propertyName)) { return flag; } } if ((propertyValue == null) && (epmSourcePathSegment != null)) { return true; } EntityPropertyMappingAttribute entityPropertyMapping = EpmWriterUtils.GetEntityPropertyMapping(epmSourcePathSegment); if (entityPropertyMapping == null) { return flag; } string str = propertyValue as string; if ((str != null) && (str.Length == 0)) { switch (entityPropertyMapping.TargetSyndicationItem) { case SyndicationItemProperty.AuthorEmail: case SyndicationItemProperty.AuthorUri: case SyndicationItemProperty.ContributorEmail: case SyndicationItemProperty.ContributorUri: return true; } } return (entityPropertyMapping.KeepInContent && flag); }
/// <summary> /// Gets the property info for the EDM property declared on this type. /// </summary> /// <param name="structuredType">The structured type to get the property on.</param> /// <param name="property">Property instance to get the property info for.</param> /// <param name="model">The model containing annotations.</param> /// <returns>Returns the PropertyInfo object for the specified EDM property.</returns> internal PropertyInfo GetPropertyInfo(IEdmStructuredType structuredType, IEdmProperty property, IEdmModel model) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(structuredType != null, "structuredType != null"); Debug.Assert(property != null, "property != null"); Debug.Assert(model != null, "model != null"); Debug.Assert(property.GetCanReflectOnInstanceTypeProperty(model), "property.CanReflectOnInstanceTypeProperty()"); #if DEBUG Debug.Assert(structuredType.ContainsProperty(property), "The structuredType does not define the specified property."); #endif if (this.propertyInfosDeclaredOnThisType == null) { this.propertyInfosDeclaredOnThisType = new Dictionary<IEdmProperty, PropertyInfo>(ReferenceEqualityComparer<IEdmProperty>.Instance); } PropertyInfo propertyInfo; if (!this.propertyInfosDeclaredOnThisType.TryGetValue(property, out propertyInfo)) { BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance; propertyInfo = structuredType.GetInstanceType(model).GetProperty(property.Name, bindingFlags); if (propertyInfo == null) { throw new ODataException(Strings.PropertyInfoTypeAnnotation_CannotFindProperty(structuredType.ODataFullName(), structuredType.GetInstanceType(model), property.Name)); } this.propertyInfosDeclaredOnThisType.Add(property, propertyInfo); } Debug.Assert(propertyInfo != null, "propertyInfo != null"); return propertyInfo; }
/// <summary> /// Constructs a new SelectBinder. /// </summary> /// <param name="model">The model used for binding.</param> /// <param name="edmType">The entity type that the $select is being applied to.</param> /// <param name="maxDepth">the maximum recursive depth.</param> /// <param name="expandClauseToDecorate">The already built expand clause to decorate</param> /// <param name="resolver">Resolver for uri parser.</param> public SelectBinder(IEdmModel model, IEdmStructuredType edmType, int maxDepth, SelectExpandClause expandClauseToDecorate, ODataUriResolver resolver = null) { ExceptionUtils.CheckArgumentNotNull(model, "tokenIn"); ExceptionUtils.CheckArgumentNotNull(edmType, "entityType"); this.visitor = new SelectPropertyVisitor(model, edmType, maxDepth, expandClauseToDecorate, resolver); }
public static IReadOnlyDictionary<string, object> CreatePropertyDictionary( this Delta entity, IEdmStructuredType edmType, ApiBase api, bool isCreation) { var propertiesAttributes = RetrievePropertiesAttributes(edmType, api); Dictionary<string, object> propertyValues = new Dictionary<string, object>(); foreach (string propertyName in entity.GetChangedPropertyNames()) { PropertyAttributes attributes; if (propertiesAttributes != null && propertiesAttributes.TryGetValue(propertyName, out attributes)) { if ((isCreation && (attributes & PropertyAttributes.IgnoreForCreation) != PropertyAttributes.None) || (!isCreation && (attributes & PropertyAttributes.IgnoreForUpdate) != PropertyAttributes.None)) { // Will not get the properties for update or creation continue; } } object value; if (entity.TryGetPropertyValue(propertyName, out value)) { var complexObj = value as EdmComplexObject; if (complexObj != null) { value = CreatePropertyDictionary(complexObj, complexObj.ActualEdmType, api, isCreation); } propertyValues.Add(propertyName, value); } } return propertyValues; }
protected EdmProperty(IEdmStructuredType declaringType, string name, IEdmTypeReference type) : base(name) { this.dependents = new HashSetInternal<IDependent>(); EdmUtil.CheckArgumentNull<IEdmStructuredType>(declaringType, "declaringType"); EdmUtil.CheckArgumentNull<IEdmTypeReference>(type, "type"); this.declaringType = declaringType; this.type = type; }
protected EdmStructuredType(bool isAbstract, bool isOpen, IEdmStructuredType baseStructuredType) { this.declaredProperties = new List<IEdmProperty>(); this.propertiesDictionary = new Cache<EdmStructuredType, IDictionary<string, IEdmProperty>>(); this.isAbstract = isAbstract; this.isOpen = isOpen; this.baseStructuredType = baseStructuredType; }
/// <summary> /// Build a property visitor to visit the select tree and decorate a SelectExpandClause /// </summary> /// <param name="model">The model used for binding.</param> /// <param name="edmType">The entity type that the $select is being applied to.</param> /// <param name="maxDepth">the maximum recursive depth.</param> /// <param name="expandClauseToDecorate">The already built expand clause to decorate</param> /// <param name="resolver">Resolver for uri parser.</param> public SelectPropertyVisitor(IEdmModel model, IEdmStructuredType edmType, int maxDepth, SelectExpandClause expandClauseToDecorate, ODataUriResolver resolver) { this.model = model; this.edmType = edmType; this.maxDepth = maxDepth; this.expandClauseToDecorate = expandClauseToDecorate; this.resolver = resolver ?? ODataUriResolver.Default; }
/// <summary> /// Initializes a new instance of the <see cref="EdmProperty"/> class. /// </summary> /// <param name="declaringType">The type that declares this property.</param> /// <param name="name">Name of the property.</param> /// <param name="type">Type of the property.</param> protected EdmProperty(IEdmStructuredType declaringType, string name, IEdmTypeReference type) : base(name) { EdmUtil.CheckArgumentNull(declaringType, "declaringType"); EdmUtil.CheckArgumentNull(type, "type"); this.declaringType = declaringType; this.type = type; }
/// <summary> /// Build the ExpandOption variant of an SelectExpandBinder /// </summary> /// <param name="configuration">The configuration used for binding.</param> /// <param name="edmType">The type of the top level expand item.</param> /// <param name="navigationSource">The navigation source of the top level expand item.</param> public SelectExpandBinder(ODataUriParserConfiguration configuration, IEdmStructuredType edmType, IEdmNavigationSource navigationSource) { ExceptionUtils.CheckArgumentNotNull(configuration, "configuration"); ExceptionUtils.CheckArgumentNotNull(edmType, "edmType"); this.configuration = configuration; this.edmType = edmType; this.navigationSource = navigationSource; }
/// <summary> /// Initializes a new instance of the <see cref="MetadataProviderEdmStructuralProperty"/> class. /// </summary> /// <param name="declaringType">The type that declares this property.</param> /// <param name="resourceProperty">The resource-property this edm property is based on.</param> /// <param name="type">The type of the property.</param> /// <param name="defaultValue">The default value of this property.</param> /// <param name="concurrencyMode">The concurrency mode of this property.</param> public MetadataProviderEdmStructuralProperty( IEdmStructuredType declaringType, ResourceProperty resourceProperty, IEdmTypeReference type, string defaultValue, EdmConcurrencyMode concurrencyMode) : base(declaringType, resourceProperty.Name, type, defaultValue, concurrencyMode) { this.ResourceProperty = resourceProperty; }
/// <summary> /// Initializes a new instance of the <see cref="EdmStructuredObject"/> class. /// </summary> /// <param name="edmType">The <see cref="IEdmStructuredTypeReference"/> of this object.</param> /// <param name="isNullable">true if this object can be nullable; otherwise, false.</param> protected EdmStructuredObject(IEdmStructuredType edmType, bool isNullable) { if (edmType == null) { throw Error.ArgumentNull("edmType"); } _expectedEdmType = edmType; _actualEdmType = edmType; IsNullable = isNullable; }
public BadProperty(IEdmStructuredType declaringType, string name, IEnumerable<EdmError> errors) : base(errors) { this.type = new Cache<BadProperty, IEdmTypeReference>(); string str = name; string empty = str; if (str == null) { empty = string.Empty; } this.name = empty; this.declaringType = declaringType; }
/// <summary> /// Validates that a property with the specified name exists on a given structured type. /// The structured type can be null if no metadata is available. /// </summary> /// <param name="propertyName">The name of the property to validate.</param> /// <param name="owningStructuredType">The owning type of the property with name <paramref name="propertyName"/> /// or null if no metadata is available.</param> /// <param name="throwOnMissingProperty">Whether throw exception on missing property.</param> /// <returns>The <see cref="IEdmProperty"/> instance representing the property with name <paramref name="propertyName"/> /// or null if no metadata is available.</returns> public IEdmProperty ValidatePropertyDefined( string propertyName, IEdmStructuredType owningStructuredType, bool throwOnMissingProperty = true) { if (owningStructuredType == null) { return null; } return owningStructuredType.FindProperty(propertyName); }
private IEdmEntityObject Createchool(int id, DateTimeOffset dto, IEdmStructuredType edmType) { IEdmNavigationProperty navigationProperty = edmType.DeclaredProperties.OfType<EdmNavigationProperty>().FirstOrDefault(e => e.Name == "School"); if (navigationProperty == null) { return null; } EdmEntityObject entity = new EdmEntityObject(navigationProperty.ToEntityType()); entity.TrySetPropertyValue("ID", id); entity.TrySetPropertyValue("CreatedDay", dto); return entity; }
internal static IEdmProperty FindDefinedProperty(string propertyName, IEdmStructuredType owningStructuredType, ODataMessageReaderSettings messageReaderSettings) { if (owningStructuredType == null) { return null; } IEdmProperty property = owningStructuredType.FindProperty(propertyName); if (((property == null) && owningStructuredType.IsOpen) && (messageReaderSettings.UndeclaredPropertyBehaviorKinds != ODataUndeclaredPropertyBehaviorKinds.None)) { throw new ODataException(Microsoft.Data.OData.Strings.ReaderValidationUtils_UndeclaredPropertyBehaviorKindSpecifiedForOpenType(propertyName, owningStructuredType.ODataFullName())); } return property; }
private IEdmEntityObject CreateDetailInfo(int id, string title, IEdmStructuredType edmType) { IEdmNavigationProperty navigationProperty = edmType.DeclaredProperties.OfType<EdmNavigationProperty>().FirstOrDefault(e => e.Name == "DetailInfo"); if (navigationProperty == null) { return null; } EdmEntityObject entity = new EdmEntityObject(navigationProperty.ToEntityType()); entity.TrySetPropertyValue("ID", id); entity.TrySetPropertyValue("Title", title); return entity; }
/// <summary> /// Gets the property info annotation for the specified type or creates a new one if it doesn't exist. /// </summary> /// <param name="structuredType">The type to get the annotation for.</param> /// <param name="model">The model containing annotations.</param> /// <returns>The property info annotation.</returns> internal static PropertyInfoTypeAnnotation GetPropertyInfoTypeAnnotation(IEdmStructuredType structuredType, IEdmModel model) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(structuredType != null, "structuredType != null"); Debug.Assert(model != null, "model != null"); PropertyInfoTypeAnnotation propertyInfoTypeAnnotation = model.GetAnnotationValue<PropertyInfoTypeAnnotation>(structuredType); if (propertyInfoTypeAnnotation == null) { propertyInfoTypeAnnotation = new PropertyInfoTypeAnnotation(); model.SetAnnotationValue(structuredType, propertyInfoTypeAnnotation); } return propertyInfoTypeAnnotation; }
/// <summary> /// Validates a stream reference property. /// </summary> /// <param name="streamProperty">The stream property to check.</param> /// <param name="structuredType">The owning type of the stream property or null if no metadata is available.</param> /// <param name="streamEdmProperty">The stream property defined by the model.</param> /// <param name="messageReaderSettings">The message reader settings being used.</param> internal static void ValidateStreamReferenceProperty(ODataProperty streamProperty, IEdmStructuredType structuredType, IEdmProperty streamEdmProperty, ODataMessageReaderSettings messageReaderSettings) { Debug.Assert(streamProperty != null, "streamProperty != null"); ValidationUtils.ValidateStreamReferenceProperty(streamProperty, streamEdmProperty); if (structuredType != null && structuredType.IsOpen) { // If no property match was found in the metadata and an error wasn't raised, // it is an open property (which is not supported for streams). if (streamEdmProperty == null && !messageReaderSettings.ReportUndeclaredLinkProperties) { // Fails with the correct error message. ValidationUtils.ValidateOpenPropertyValue(streamProperty.Name, streamProperty.Value); } } }
/// <summary> /// Validates a stream reference property. /// </summary> /// <param name="streamProperty">The stream property to check.</param> /// <param name="structuredType">The owning type of the stream property or null if no metadata is available.</param> /// <param name="streamEdmProperty">The stream property defined by the model.</param> internal static void ValidateStreamReferenceProperty(ODataProperty streamProperty, IEdmStructuredType structuredType, IEdmProperty streamEdmProperty) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(streamProperty != null, "streamProperty != null"); ValidationUtils.ValidateStreamReferenceProperty(streamProperty, streamEdmProperty); if (structuredType != null && structuredType.IsOpen) { // If no property match was found in the metadata and an error wasn't raised, // it is an open property (which is not supported for streams). if (streamEdmProperty == null) { // Fails with the correct error message. ValidationUtils.ValidateOpenPropertyValue(streamProperty.Name, streamProperty.Value); } } }
private IEdmProperty CreateEdmProperty(IEdmStructuredType declaringType, PropertyInfo propertyInfo) { IEdmProperty property; IEdmType edmType = this.GetOrCreateEdmTypeInternal(propertyInfo.PropertyType).EdmType; bool isNullable = ClientTypeUtil.CanAssignNull(propertyInfo.PropertyType); if ((edmType.TypeKind == EdmTypeKind.Entity) || ((edmType.TypeKind == EdmTypeKind.Collection) && (((IEdmCollectionType) edmType).ElementType.TypeKind() == EdmTypeKind.Entity))) { IEdmEntityType type2 = declaringType as IEdmEntityType; if (type2 == null) { throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.ClientTypeCache_NonEntityTypeCannotContainEntityProperties(propertyInfo.Name, propertyInfo.DeclaringType.ToString())); } property = EdmNavigationProperty.CreateNavigationPropertyWithPartner(propertyInfo.Name, edmType.ToEdmTypeReference(isNullable), null, false, EdmOnDeleteAction.None, "Partner", type2.ToEdmTypeReference(true), null, false, EdmOnDeleteAction.None); } else { property = new EdmStructuralProperty(declaringType, propertyInfo.Name, edmType.ToEdmTypeReference(isNullable)); } property.SetClientPropertyAnnotation(new ClientPropertyAnnotation(property, propertyInfo, this.protocolVersion)); return property; }
/// <summary> /// Add semantic meaning to a Select or Expand Token /// </summary> /// <param name="elementType">the top level entity type.</param> /// <param name="navigationSource">the top level navigation source</param> /// <param name="expandToken">the syntactically parsed expand token</param> /// <param name="selectToken">the syntactically parsed select token</param> /// <param name="configuration">The configuration to use for parsing.</param> /// <returns>A select expand clause bound to metadata.</returns> public SelectExpandClause Bind( IEdmStructuredType elementType, IEdmNavigationSource navigationSource, ExpandToken expandToken, SelectToken selectToken, ODataUriParserConfiguration configuration) { ExpandToken unifiedSelectExpandToken = SelectExpandSyntacticUnifier.Combine(expandToken, selectToken); ExpandTreeNormalizer expandTreeNormalizer = new ExpandTreeNormalizer(); ExpandToken normalizedSelectExpandToken = expandTreeNormalizer.NormalizeExpandTree(unifiedSelectExpandToken); SelectExpandBinder selectExpandBinder = new SelectExpandBinder(configuration, elementType, navigationSource); SelectExpandClause clause = selectExpandBinder.Bind(normalizedSelectExpandToken); SelectExpandClauseFinisher.AddExplicitNavPropLinksWhereNecessary(clause); new ExpandDepthAndCountValidator(configuration.Settings.MaximumExpansionDepth, configuration.Settings.MaximumExpansionCount).Validate(clause); return clause; }
/// <summary> /// Follow any type segments on the path, stopping at the first segment that isn't a type token. /// </summary> /// <param name="firstTypeToken">the first type segment</param> /// <param name="model">the model these types are contained in.</param> /// <param name="maxDepth">the maximum recursive depth</param> /// <param name="resolver">Resolver for uri parser.</param> /// <param name="currentLevelType">the top level type, will be overwritten with the last entity type in the chain</param> /// <param name="firstNonTypeToken">the first non type token in the path</param> /// <returns>A path with type segments added to it.</returns> public static IEnumerable<ODataPathSegment> FollowTypeSegments(PathSegmentToken firstTypeToken, IEdmModel model, int maxDepth, ODataUriResolver resolver, ref IEdmStructuredType currentLevelType, out PathSegmentToken firstNonTypeToken) { ExceptionUtils.CheckArgumentNotNull(firstTypeToken, "firstTypeToken"); ExceptionUtils.CheckArgumentNotNull(model, "model"); if (!firstTypeToken.IsNamespaceOrContainerQualified()) { throw new ODataException(ODataErrorStrings.SelectExpandPathBinder_FollowNonTypeSegment(firstTypeToken.Identifier)); } int index = 0; List<ODataPathSegment> pathToReturn = new List<ODataPathSegment>(); PathSegmentToken currentToken = firstTypeToken; while (currentToken.IsNamespaceOrContainerQualified() && currentToken.NextToken != null) { IEdmType previousLevelEntityType = currentLevelType; currentLevelType = UriEdmHelpers.FindTypeFromModel(model, currentToken.Identifier, resolver) as IEdmStructuredType; if (currentLevelType == null) { // TODO: fix this error message? throw new ODataException(ODataErrorStrings.ExpandItemBinder_CannotFindType(currentToken.Identifier)); } UriEdmHelpers.CheckRelatedTo(previousLevelEntityType, currentLevelType); pathToReturn.Add(new TypeSegment(currentLevelType, /*entitySet*/null)); index++; currentToken = currentToken.NextToken; if (index >= maxDepth) { throw new ODataException(ODataErrorStrings.ExpandItemBinder_PathTooDeep); } } firstNonTypeToken = currentToken; return pathToReturn; }
/// <summary> /// Validates that a property with the specified name exists on a given structured type. /// The structured type can be null if no metadata is available. /// </summary> /// <param name="propertyName">The name of the property to validate.</param> /// <param name="owningStructuredType">The owning type of the property with name <paramref name="propertyName"/> /// or null if no metadata is available.</param> /// <param name="throwOnMissingProperty">Whether throw exception on missing property.</param> /// <returns>The <see cref="IEdmProperty"/> instance representing the property with name <paramref name="propertyName"/> /// or null if no metadata is available.</returns> internal static IEdmProperty ValidatePropertyDefined( string propertyName, IEdmStructuredType owningStructuredType, bool throwOnMissingProperty = true) { Debug.Assert(!string.IsNullOrEmpty(propertyName), "!string.IsNullOrEmpty(propertyName)"); if (owningStructuredType == null) { return null; } IEdmProperty property = owningStructuredType.FindProperty(propertyName); // verify that the property is declared if the type is not an open type. if (throwOnMissingProperty && !owningStructuredType.IsOpen && property == null) { throw new ODataException(Strings.ValidationUtils_PropertyDoesNotExistOnType(propertyName, owningStructuredType.FullTypeName())); } return property; }
/// <summary> /// Parse the raw select and expand strings into Abstract Syntax Trees /// </summary> /// <param name="selectClause">the raw select string</param> /// <param name="expandClause">the raw expand string</param> /// <param name="parentEntityType">the parent entity type for expand option</param> /// <param name="configuration">the OData URI parser configuration</param> /// <param name="expandTree">the resulting expand AST</param> /// <param name="selectTree">the resulting select AST</param> public static void Parse( string selectClause, string expandClause, IEdmStructuredType parentEntityType, ODataUriParserConfiguration configuration, out ExpandToken expandTree, out SelectToken selectTree) { SelectExpandParser selectParser = new SelectExpandParser(selectClause, configuration.Settings.SelectExpandLimit, configuration.EnableCaseInsensitiveUriFunctionIdentifier) { MaxPathDepth = configuration.Settings.PathLimit }; selectTree = selectParser.ParseSelect(); SelectExpandParser expandParser = new SelectExpandParser(configuration.Resolver, expandClause, parentEntityType, configuration.Settings.SelectExpandLimit, configuration.EnableCaseInsensitiveUriFunctionIdentifier) { MaxPathDepth = configuration.Settings.PathLimit, MaxFilterDepth = configuration.Settings.FilterLimit, MaxOrderByDepth = configuration.Settings.OrderByLimit, MaxSearchDepth = configuration.Settings.SearchLimit }; expandTree = expandParser.ParseExpand(); }
/// <summary> /// Build a segment from a token. /// </summary> /// <param name="tokenIn">the token to bind</param> /// <param name="model">The model.</param> /// <param name="edmType">the type of the current scope based on type segments.</param> /// <param name="resolver">Resolver for uri parser.</param> /// <returns>The segment created from the token.</returns> public static ODataPathSegment ConvertNonTypeTokenToSegment(PathSegmentToken tokenIn, IEdmModel model, IEdmStructuredType edmType, ODataUriResolver resolver = null) { if (resolver == null) { resolver = ODataUriResolver.Default; } ODataPathSegment nextSegment; if (TryBindAsDeclaredProperty(tokenIn, edmType, resolver, out nextSegment)) { return nextSegment; } // Operations must be container-qualified, and because the token type indicates it was not a .-seperated identifier, we should not try to look up operations. if (tokenIn.IsNamespaceOrContainerQualified()) { if (TryBindAsOperation(tokenIn, model, edmType, out nextSegment)) { return nextSegment; } // If an action or function is requested in a selectItem using a qualifiedActionName or a qualifiedFunctionName // and that operation cannot be bound to the entities requested, the service MUST ignore the selectItem. if (!edmType.IsOpen) { return null; } } if (edmType.IsOpen) { return new OpenPropertySegment(tokenIn.Identifier); } throw new ODataException(ODataErrorStrings.MetadataBinder_PropertyNotDeclared(edmType.ODataFullName(), tokenIn.Identifier)); }
/// <summary> /// Finds a list of types that derive directly from the supplied type. /// </summary> /// <param name="baseType">The base type that derived types are being searched for.</param> /// <returns>A list of types that derive directly from the base type.</returns> public abstract IEnumerable <IEdmStructuredType> FindDirectlyDerivedTypes(IEdmStructuredType baseType);
/// <summary> /// Validates that a property with the specified name exists on a given structured type. /// The structured type can be null if no metadata is available. /// </summary> /// <param name="propertyName">Name of the property.</param> /// <param name="owningStructuredType">Hosting type of the property or null if no metadata is /// available.</param> /// <returns>An <see cref="IEdmProperty"/> instance representing the specified property or /// null if no metadata is available.</returns> public IEdmProperty ValidatePropertyDefined(string propertyName, IEdmStructuredType owningStructuredType) { return(WriterValidationUtils.ValidatePropertyDefined( propertyName, owningStructuredType, settings.ThrowOnUndeclaredPropertyForNonOpenType)); }
/// <summary> /// Deserializes the given <paramref name="resourceWrapper"/> under the given <paramref name="readContext"/>. /// </summary> /// <param name="resourceWrapper">The OData resource to deserialize.</param> /// <param name="structuredType">The type of the resource to deserialize.</param> /// <param name="readContext">The deserializer context.</param> /// <returns>The deserialized resource.</returns> public virtual object ReadResource(ODataResourceWrapper resourceWrapper, IEdmStructuredTypeReference structuredType, ODataDeserializerContext readContext) { if (resourceWrapper == null) { throw Error.ArgumentNull("resourceWrapper"); } if (readContext == null) { throw Error.ArgumentNull("readContext"); } if (!String.IsNullOrEmpty(resourceWrapper.Resource.TypeName) && structuredType.FullName() != resourceWrapper.Resource.TypeName) { // received a derived type in a base type deserializer. delegate it to the appropriate derived type deserializer. IEdmModel model = readContext.Model; if (model == null) { throw Error.Argument("readContext", SRResources.ModelMissingFromReadContext); } IEdmStructuredType actualType = model.FindType(resourceWrapper.Resource.TypeName) as IEdmStructuredType; if (actualType == null) { throw new ODataException("TODO:" /*Error.Format(SRResources.ResourceTypeNotInModel, resourceWrapper.Resource.TypeName)*/); } if (actualType.IsAbstract) { //string message = Error.Format(SRResources.CannotInstantiateAbstractResourceType, resourceWrapper.Resource.TypeName); throw new ODataException("TODO:"); } IEdmTypeReference actualStructuredType; IEdmEntityType actualEntityType = actualType as IEdmEntityType; if (actualEntityType != null) { actualStructuredType = new EdmEntityTypeReference(actualEntityType, isNullable: false); } else { actualStructuredType = new EdmComplexTypeReference(actualType as IEdmComplexType, isNullable: false); } ODataEdmTypeDeserializer deserializer = DeserializerProvider.GetEdmTypeDeserializer(actualStructuredType); if (deserializer == null) { throw new SerializationException( Error.Format(SRResources.TypeCannotBeDeserialized, actualEntityType.FullName(), typeof(ODataInputFormatter).Name)); } object resource = deserializer.ReadInline(resourceWrapper, actualStructuredType, readContext); EdmStructuredObject structuredObject = resource as EdmStructuredObject; if (structuredObject != null) { structuredObject.ExpectedEdmType = structuredType.StructuredDefinition(); } return(resource); } else { object resource = CreateResourceInstance(structuredType, readContext); ApplyResourceProperties(resource, resourceWrapper, structuredType, readContext); return(resource); } }
public JsonPropertyNameMapper(IEdmModel model, IEdmStructuredType type) { _model = model; _type = type; }
/// <summary> /// Creates a new instance of the <see cref="SelectExpandNode"/> class describing the set of structural properties, /// nested properties, navigation properties, and actions to select and expand for the given <paramref name="selectExpandClause"/>. /// </summary> /// <param name="selectExpandClause">The parsed $select and $expand query options.</param> /// <param name="structuredType">The structural type of the resource that would be written.</param> /// <param name="model">The <see cref="IEdmModel"/> that contains the given structural type.</param> public SelectExpandNode(SelectExpandClause selectExpandClause, IEdmStructuredType structuredType, IEdmModel model) : this() { Initialize(selectExpandClause, structuredType, model, false, null); }
/// <summary> /// Creates a new instance of the <see cref="SelectExpandNode"/> class describing the set of structural properties, /// nested properties, navigation properties, and actions to select and expand for the given <paramref name="selectExpandClause"/>. /// </summary> /// <param name="selectExpandClause">The parsed $select and $expand query options.</param> /// <param name="structuredType">The structural type of the resource that would be written.</param> /// <param name="model">The <see cref="IEdmModel"/> that contains the given structural type.</param> public SelectExpandNode(SelectExpandClause selectExpandClause, IEdmStructuredType structuredType, IEdmModel model) : this() { if (structuredType == null) { throw Error.ArgumentNull("structuredType"); } if (model == null) { throw Error.ArgumentNull("model"); } // So far, it includes all properties of primitive, enum and collection of them HashSet <IEdmStructuralProperty> allStructuralProperties = new HashSet <IEdmStructuralProperty>(); // So far, it includes all properties of complex and collection of complex HashSet <IEdmStructuralProperty> allComplexStructuralProperties = new HashSet <IEdmStructuralProperty>(); GetStructuralProperties(structuredType, allStructuralProperties, allComplexStructuralProperties); // So far, it includes all navigation properties HashSet <IEdmNavigationProperty> allNavigationProperties; HashSet <IEdmAction> allActions; HashSet <IEdmFunction> allFunctions; IEdmEntityType entityType = structuredType as IEdmEntityType; if (entityType != null) { allNavigationProperties = new HashSet <IEdmNavigationProperty>(entityType.NavigationProperties()); allActions = new HashSet <IEdmAction>(model.GetAvailableActions(entityType)); allFunctions = new HashSet <IEdmFunction>(model.GetAvailableFunctions(entityType)); } else { allNavigationProperties = new HashSet <IEdmNavigationProperty>(); allActions = new HashSet <IEdmAction>(); allFunctions = new HashSet <IEdmFunction>(); } if (selectExpandClause == null) { SelectedStructuralProperties = allStructuralProperties; SelectedComplexProperties = allComplexStructuralProperties; SelectedNavigationProperties = allNavigationProperties; SelectedActions = allActions; SelectedFunctions = allFunctions; SelectAllDynamicProperties = true; } else { if (selectExpandClause.AllSelected) { SelectedStructuralProperties = allStructuralProperties; SelectedComplexProperties = allComplexStructuralProperties; SelectedNavigationProperties = allNavigationProperties; SelectedActions = allActions; SelectedFunctions = allFunctions; SelectAllDynamicProperties = true; } else { BuildSelections(selectExpandClause, allStructuralProperties, allComplexStructuralProperties, allNavigationProperties, allActions, allFunctions); SelectAllDynamicProperties = false; } BuildExpansions(selectExpandClause, allNavigationProperties); // remove expanded navigation properties from the selected navigation properties. SelectedNavigationProperties.ExceptWith(ExpandedNavigationProperties.Keys); } }
/// <summary> /// Reads the content of a properties in an element (complex value, m:properties, ...) /// </summary> /// <param name="structuredType">The type which should declare the properties to be read. Optional.</param> /// <param name="properties">The list of properties to add properties to.</param> /// <param name="duplicatePropertyNamesChecker">The duplicate property names checker to use.</param> /// <remarks> /// Pre-Condition: XmlNodeType.Element - The element to read properties from. /// Post-Condition: XmlNodeType.Element - The element to read properties from if it is an empty element. /// XmlNodeType.EndElement - The end element of the element to read properties from. /// </remarks> private void ReadPropertiesImplementation(IEdmStructuredType structuredType, ReadOnlyEnumerable <ODataProperty> properties, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker) { Debug.Assert(properties != null, "properties != null"); Debug.Assert(duplicatePropertyNamesChecker != null, "duplicatePropertyNamesChecker != null"); this.AssertXmlCondition(XmlNodeType.Element); // Empty values are valid - they have no properties if (!this.XmlReader.IsEmptyElement) { // Read over the complex value element to its first child node (or end-element) this.XmlReader.ReadStartElement(); do { switch (this.XmlReader.NodeType) { case XmlNodeType.Element: if (this.XmlReader.NamespaceEquals(this.XmlReader.ODataNamespace)) { // Found a property IEdmProperty edmProperty = null; bool isOpen = false; bool ignoreProperty = false; if (structuredType != null) { // Lookup the property in metadata edmProperty = ReaderValidationUtils.ValidateValuePropertyDefined(this.XmlReader.LocalName, structuredType, this.MessageReaderSettings, out ignoreProperty); if (edmProperty != null && edmProperty.PropertyKind == EdmPropertyKind.Navigation) { throw new ODataException(ODataErrorStrings.ODataAtomPropertyAndValueDeserializer_NavigationPropertyInProperties(edmProperty.Name, structuredType)); } // If the property was not declared, it must be open. isOpen = edmProperty == null; } if (ignoreProperty) { this.XmlReader.Skip(); } else { ODataNullValueBehaviorKind nullValueReadBehaviorKind = this.ReadingResponse || edmProperty == null ? ODataNullValueBehaviorKind.Default : this.Model.NullValueReadBehaviorKind(edmProperty); ODataProperty property = this.ReadProperty( false, edmProperty == null ? null : edmProperty.Name, edmProperty == null ? null : edmProperty.Type, nullValueReadBehaviorKind); Debug.Assert( property != null || nullValueReadBehaviorKind == ODataNullValueBehaviorKind.IgnoreValue, "If we don't ignore null values the property must not be null."); if (property != null) { if (isOpen) { ValidationUtils.ValidateOpenPropertyValue(property.Name, property.Value); } duplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(property); properties.AddToSourceList(property); } } } else { this.XmlReader.Skip(); } break; case XmlNodeType.EndElement: // End of the complex value. break; default: // Non-element so for example a text node, just ignore this.XmlReader.Skip(); break; } }while (this.XmlReader.NodeType != XmlNodeType.EndElement); } }
/// <summary> /// Writes a single property in ATOM format. /// </summary> /// <param name="property">The property to write out.</param> /// <param name="owningType">The owning type for the <paramref name="property"/> or null if no metadata is available.</param> /// <param name="isTopLevel">true if writing a top-level property payload; otherwise false.</param> /// <param name="isWritingCollection">true if we are writing a top-level collection instead of an entry.</param> /// <param name="beforePropertyAction">Action which is called before the property is written, if it's going to be written.</param> /// <param name="duplicatePropertyNamesChecker">The checker instance for duplicate property names.</param> /// <param name="projectedProperties">Set of projected properties, or null if all properties should be written.</param> /// <returns>true if the property was actually written, false otherwise.</returns> private bool WriteProperty( ODataProperty property, IEdmStructuredType owningType, bool isTopLevel, bool isWritingCollection, Action beforePropertyAction, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, ProjectedPropertiesAnnotation projectedProperties) { WriterValidationUtils.ValidatePropertyNotNull(property); object value = property.Value; string propertyName = property.Name; //// TODO: If we implement type conversions the value needs to be converted here //// since the next method call needs to know if the value is a string or not in some cases. ODataComplexValue complexValue = value as ODataComplexValue; ProjectedPropertiesAnnotation complexValueProjectedProperties = null; if (!ShouldWritePropertyInContent(projectedProperties, propertyName)) { return false; } WriterValidationUtils.ValidatePropertyName(propertyName); duplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(property); IEdmProperty edmProperty = WriterValidationUtils.ValidatePropertyDefined(propertyName, owningType); IEdmTypeReference propertyTypeReference = edmProperty == null ? null : edmProperty.Type; if (value is ODataStreamReferenceValue) { throw new ODataException(ODataErrorStrings.ODataWriter_StreamPropertiesMustBePropertiesOfODataEntry(propertyName)); } // Null property value. if (value == null) { this.WriteNullPropertyValue(propertyTypeReference, propertyName, isTopLevel, isWritingCollection, beforePropertyAction); return true; } bool isOpenPropertyType = owningType != null && owningType.IsOpen && propertyTypeReference == null; if (isOpenPropertyType) { ValidationUtils.ValidateOpenPropertyValue(propertyName, value); } if (complexValue != null) { return this.WriteComplexValueProperty( complexValue, propertyName, isTopLevel, isWritingCollection, beforePropertyAction, propertyTypeReference, isOpenPropertyType, complexValueProjectedProperties); } ODataCollectionValue collectionValue = value as ODataCollectionValue; if (collectionValue != null) { this.WriteCollectionValueProperty( collectionValue, propertyName, isTopLevel, isWritingCollection, beforePropertyAction, propertyTypeReference, isOpenPropertyType); return true; } // If the value isn't one of the value types tested for already, it must be a non-null primitive or enum type. this.WritePropertyStart(beforePropertyAction, property, isWritingCollection, isTopLevel); SerializationTypeNameAnnotation serializationTypeNameAnnotation = property.ODataValue.GetAnnotation<SerializationTypeNameAnnotation>(); ODataEnumValue enumValue = value as ODataEnumValue; if (enumValue != null) { this.WriteEnumValue(enumValue, /*collectionValidator*/ null, propertyTypeReference, serializationTypeNameAnnotation); } else { this.WritePrimitiveValue(value, /*collectionValidator*/ null, propertyTypeReference, serializationTypeNameAnnotation); } this.WritePropertyEnd(); return true; }
public TestEdmStructuredObject(IEdmStructuredType edmType, bool isNullable) : base(edmType, isNullable) { }
public static IEdmStructuralProperty AssertHasPrimitiveProperty(this IEdmStructuredType edmType, IEdmModel model, string propertyName, EdmPrimitiveTypeKind primitiveTypeKind, bool isNullable) { Type primitiveType = EdmLibHelpers.GetClrType(new EdmPrimitiveTypeReference(EdmCoreModel.Instance.GetPrimitiveType(primitiveTypeKind), isNullable), model); return(edmType.AssertHasProperty <IEdmStructuralProperty>(model, propertyName, primitiveType, isNullable)); }
/// <summary> /// Creates an <see cref="ODataReader" /> to read a resource. /// </summary> /// <param name="navigationSource">The navigation source we are going to read resources for.</param> /// <param name="expectedResourceType">The expected resource type for the resource to be read.</param> /// <returns>The newly created <see cref="ODataReader"/>.</returns> public override ODataReader CreateResourceReader(IEdmNavigationSource navigationSource, IEdmStructuredType expectedResourceType) { this.AssertSynchronous(); this.VerifyCanCreateODataReader(navigationSource, expectedResourceType); return(this.CreateResourceReaderImplementation(navigationSource, expectedResourceType)); }
/// <summary> /// Asynchronously creates an <see cref="ODataReader" /> to read a delta resource set. /// </summary> /// <param name="entitySet">The entity set we are going to read resources for.</param> /// <param name="expectedResourceType">The expected structured type for the items in the resource set.</param> /// <returns>Task which when completed returns the newly created <see cref="ODataReader"/>.</returns> public override Task <ODataReader> CreateDeltaResourceSetReaderAsync(IEdmEntitySetBase entitySet, IEdmStructuredType expectedResourceType) { this.AssertAsynchronous(); this.VerifyCanCreateODataReader(entitySet, expectedResourceType); // Note that the reading is actually synchronous since we buffer the entire input when getting the stream from the message. return(TaskUtils.GetTaskForSynchronousOperation(() => this.CreateResourceSetReaderImplementation(entitySet, expectedResourceType, /*readingParameter*/ false, /*readingDelta*/ true))); }
/// <summary> /// Initializes a new instance of the <see cref="EdmStructuredObject"/> class. /// </summary> /// <param name="edmType">The <see cref="IEdmStructuredType"/> of this object.</param> protected EdmStructuredObject(IEdmStructuredType edmType) : this(edmType, isNullable : false) { }
private IEdmVocabularyAnnotatable ComputeTarget() { if (this.targetContext != null) { return(this.targetContext); } else { Debug.Assert(this.annotationsContext != null, "Annotation must either have a target context or annotations context"); string target = this.annotationsContext.Annotations.Target; string[] targetSegments = target.Split('/'); int targetSegmentsCount = targetSegments.Count(); IEdmEntityContainer container; if (targetSegmentsCount == 1) { string elementName = targetSegments[0]; IEdmSchemaType type = this.schema.FindType(elementName); if (type != null) { return(type); } IEdmTerm term = this.schema.FindTerm(elementName); if (term != null) { return(term); } IEdmOperation operation = this.FindParameterizedOperation(elementName, this.Schema.FindOperations, this.CreateAmbiguousOperation); if (operation != null) { return(operation); } container = this.schema.FindEntityContainer(elementName); if (container != null) { return(container); } return(new UnresolvedType(this.Schema.UnresolvedName(targetSegments[0]), this.Location)); } if (targetSegmentsCount == 2) { container = this.schema.FindEntityContainer(targetSegments[0]); if (container != null) { IEdmEntityContainerElement containerElement = container.FindEntitySetExtended(targetSegments[1]); if (containerElement != null) { return(containerElement); } IEdmOperationImport operationImport = this.FindParameterizedOperationImport(targetSegments[1], container.FindOperationImportsExtended, this.CreateAmbiguousOperationImport); if (operationImport != null) { return(operationImport); } return(new UnresolvedEntitySet(targetSegments[1], container, this.Location)); } IEdmStructuredType type = this.schema.FindType(targetSegments[0]) as IEdmStructuredType; if (type != null) { IEdmProperty property = type.FindProperty(targetSegments[1]); if (property != null) { return(property); } return(new UnresolvedProperty(type, targetSegments[1], this.Location)); } IEdmOperation operation = this.FindParameterizedOperation(targetSegments[0], this.Schema.FindOperations, this.CreateAmbiguousOperation); if (operation != null) { IEdmOperationParameter parameter = operation.FindParameter(targetSegments[1]); if (parameter != null) { return(parameter); } return(new UnresolvedParameter(operation, targetSegments[1], this.Location)); } return(new UnresolvedProperty(new UnresolvedEntityType(this.Schema.UnresolvedName(targetSegments[0]), this.Location), targetSegments[1], this.Location)); } if (targetSegmentsCount == 3) { // The only valid target with three segments is a function parameter. string containerName = targetSegments[0]; string operationName = targetSegments[1]; string parameterName = targetSegments[2]; container = this.Model.FindEntityContainer(containerName); if (container != null) { IEdmOperationImport operationImport = this.FindParameterizedOperationImport(operationName, container.FindOperationImportsExtended, this.CreateAmbiguousOperationImport); if (operationImport != null) { IEdmOperationParameter parameter = operationImport.Operation.FindParameter(parameterName); if (parameter != null) { return(parameter); } return(new UnresolvedParameter(operationImport.Operation, parameterName, this.Location)); } } string qualifiedOperationName = containerName + "/" + operationName; UnresolvedOperation unresolvedOperation = new UnresolvedOperation(qualifiedOperationName, Edm.Strings.Bad_UnresolvedOperation(qualifiedOperationName), this.Location); return(new UnresolvedParameter(unresolvedOperation, parameterName, this.Location)); } return(new BadElement(new EdmError[] { new EdmError(this.Location, EdmErrorCode.ImpossibleAnnotationsTarget, Edm.Strings.CsdlSemantics_ImpossibleAnnotationsTarget(target)) })); } }
/// <summary> /// Tries to bind a given token as an Operation. /// </summary> /// <param name="pathToken">Token to bind.</param> /// <param name="model">The model.</param> /// <param name="entityType">the current entity type to use as the binding type when looking for operations.</param> /// <param name="segment">Bound segment if the token was bound to an operation successfully, or null.</param> /// <returns>True if the token was bound successfully, or false otherwise.</returns> internal static bool TryBindAsOperation(PathSegmentToken pathToken, IEdmModel model, IEdmStructuredType entityType, out ODataPathSegment segment) { ExceptionUtils.CheckArgumentNotNull(pathToken, "pathToken"); ExceptionUtils.CheckArgumentNotNull(entityType, "entityType"); IEnumerable <IEdmOperation> possibleFunctions = Enumerable.Empty <IEdmOperation>(); IList <string> parameterNames = new List <string>(); // Catch all catchable exceptions as FindDeclaredBoundOperations is implemented by anyone. // If an exception occurs it will be suppressed and the possible functions will be empty and return false. try { int wildCardPos = pathToken.Identifier.IndexOf("*", StringComparison.Ordinal); if (wildCardPos > -1) { string namespaceName = pathToken.Identifier.Substring(0, wildCardPos - 1); possibleFunctions = model.FindBoundOperations(entityType).Where(o => o.Namespace == namespaceName); } else { NonSystemToken nonSystemToken = pathToken as NonSystemToken; if (nonSystemToken != null && nonSystemToken.NamedValues != null) { parameterNames = nonSystemToken.NamedValues.Select(s => s.Name).ToList(); } if (parameterNames.Count > 0) { // Always force to use fully qualified name when select operation possibleFunctions = model.FindBoundOperations(entityType).FilterByName(true, pathToken.Identifier).FilterOperationsByParameterNames(parameterNames, false); } else { possibleFunctions = model.FindBoundOperations(entityType).FilterByName(true, pathToken.Identifier); } } } catch (Exception exc) { if (!ExceptionUtils.IsCatchableExceptionType(exc)) { throw; } } // Only filter if there is more than one and its needed. if (possibleFunctions.Count() > 1) { possibleFunctions = possibleFunctions.FilterBoundOperationsWithSameTypeHierarchyToTypeClosestToBindingType(entityType); // If more than one overload matches, try to select based on optional parameters if (parameterNames.Count > 0 && possibleFunctions.Count() > 1) { possibleFunctions = possibleFunctions.FilterOverloadsBasedOnParameterCount(parameterNames.Count); } } if (!possibleFunctions.HasAny()) { segment = null; return(false); } possibleFunctions.EnsureOperationsBoundWithBindingParameter(); segment = new OperationSegment(possibleFunctions, null /*entitySet*/); return(true); }
public NoneKinds2(string namespaceName, string name, IEdmTypeReference type, IEdmStructuredType declaringType) { this.Namespace = namespaceName; this.Name = name; this.Type = type; this.DeclaringType = declaringType; PropertyKind = EdmPropertyKind.None; SchemaElementKind = EdmSchemaElementKind.None; PrimitiveKind = EdmPrimitiveTypeKind.None; TypeKind = EdmTypeKind.None; }
/// <summary> /// Creates an <see cref="ODataReader" /> to read a resource. /// </summary> /// <param name="navigationSource">The navigation source we are going to read resources for.</param> /// <param name="expectedBaseResourceType">The expected structured type for the resource to be read.</param> /// <returns>The newly created <see cref="ODataReader"/>.</returns> private ODataReader CreateResourceReaderImplementation(IEdmNavigationSource navigationSource, IEdmStructuredType expectedBaseResourceType) { return(new ODataJsonLightReader(this, navigationSource, expectedBaseResourceType, false)); }
/// <summary> /// Creates a new instance of the <see cref="SelectExpandNode"/> class describing the set of structural properties, /// nested properties, navigation properties, and actions to select and expand for the given <paramref name="writeContext"/>. /// </summary> /// <param name="structuredType">The structural type of the resource that would be written.</param> /// <param name="writeContext">The serializer context to be used while creating the collection.</param> /// <remarks>The default constructor is for unit testing only.</remarks> public SelectExpandNode(IEdmStructuredType structuredType, ODataSerializerContext writeContext) : this(writeContext.SelectExpandClause, structuredType, writeContext.Model) { }
protected virtual void ProcessStructuredType(IEdmStructuredType definition) { this.ProcessType(definition); this.VisitProperties(definition.DeclaredProperties); }
public IEnumerable <IEdmStructuredType> FindDirectlyDerivedTypes(IEdmStructuredType baseType) { return(this.primaryModel.FindDirectlyDerivedTypes(baseType)); }
/// <summary> /// Generate an expand item (and a select item for the implicit nav prop if necessary) based on an ExpandTermToken /// </summary> /// <param name="tokenIn">the expandTerm token to visit</param> /// <returns>the expand item for this expand term token.</returns> private SelectItem GenerateExpandItem(ExpandTermToken tokenIn) { ExceptionUtils.CheckArgumentNotNull(tokenIn, "tokenIn"); PathSegmentToken currentToken = tokenIn.PathToNavigationProp; IEdmStructuredType currentLevelEntityType = this.EdmType; List <ODataPathSegment> pathSoFar = new List <ODataPathSegment>(); PathSegmentToken firstNonTypeToken = currentToken; if (currentToken.IsNamespaceOrContainerQualified()) { pathSoFar.AddRange(SelectExpandPathBinder.FollowTypeSegments(currentToken, this.Model, this.Settings.SelectExpandLimit, this.configuration.Resolver, ref currentLevelEntityType, out firstNonTypeToken)); } IEdmProperty edmProperty = this.configuration.Resolver.ResolveProperty(currentLevelEntityType, firstNonTypeToken.Identifier); if (edmProperty == null) { throw new ODataException(ODataErrorStrings.MetadataBinder_PropertyNotDeclared(currentLevelEntityType.FullTypeName(), currentToken.Identifier)); } IEdmNavigationProperty currentNavProp = edmProperty as IEdmNavigationProperty; IEdmStructuralProperty currentComplexProp = edmProperty as IEdmStructuralProperty; if (currentNavProp == null && currentComplexProp == null) { throw new ODataException(ODataErrorStrings.ExpandItemBinder_PropertyIsNotANavigationPropertyOrComplexProperty(currentToken.Identifier, currentLevelEntityType.FullTypeName())); } if (currentComplexProp != null) { currentNavProp = ParseComplexTypesBeforeNavigation(currentComplexProp, ref firstNonTypeToken, pathSoFar); } // ensure that we're always dealing with proper V4 syntax if (firstNonTypeToken.NextToken != null && firstNonTypeToken.NextToken.NextToken != null) { throw new ODataException(ODataErrorStrings.ExpandItemBinder_TraversingMultipleNavPropsInTheSamePath); } bool isRef = false; if (firstNonTypeToken.NextToken != null) { // lastly... make sure that, since we're on a NavProp, that the next token isn't null. if (firstNonTypeToken.NextToken.Identifier == UriQueryConstants.RefSegment) { isRef = true; } else { throw new ODataException(ODataErrorStrings.ExpandItemBinder_TraversingMultipleNavPropsInTheSamePath); } } // Add the segments in select and expand to parsed segments this.parsedSegments.AddRange(pathSoFar); IEdmNavigationSource targetNavigationSource = null; if (this.NavigationSource != null) { IEdmPathExpression bindingPath; targetNavigationSource = this.NavigationSource.FindNavigationTarget(currentNavProp, BindingPathHelper.MatchBindingPath, this.parsedSegments, out bindingPath); } NavigationPropertySegment navSegment = new NavigationPropertySegment(currentNavProp, targetNavigationSource); pathSoFar.Add(navSegment); this.parsedSegments.Add(navSegment); // Add the navigation property segment to parsed segments for future usage. ODataExpandPath pathToNavProp = new ODataExpandPath(pathSoFar); ApplyClause applyOption = null; if (tokenIn.ApplyOptions != null) { MetadataBinder binder = this.BuildNewMetadataBinder(targetNavigationSource); ApplyBinder applyBinder = new ApplyBinder(binder.Bind, binder.BindingState); applyOption = applyBinder.BindApply(tokenIn.ApplyOptions); } ComputeClause computeOption = null; if (tokenIn.ComputeOption != null) { MetadataBinder binder = this.BuildNewMetadataBinder(targetNavigationSource); ComputeBinder computeBinder = new ComputeBinder(binder.Bind); computeOption = computeBinder.BindCompute(tokenIn.ComputeOption); } var generatedProperties = GetGeneratedProperties(computeOption, applyOption); bool collapsed = applyOption?.Transformations.Any(t => t.Kind == TransformationNodeKind.Aggregate || t.Kind == TransformationNodeKind.GroupBy) ?? false; // call MetadataBinder to build the filter clause FilterClause filterOption = null; if (tokenIn.FilterOption != null) { MetadataBinder binder = this.BuildNewMetadataBinder(targetNavigationSource, generatedProperties, collapsed); FilterBinder filterBinder = new FilterBinder(binder.Bind, binder.BindingState); filterOption = filterBinder.BindFilter(tokenIn.FilterOption); } // call MetadataBinder again to build the orderby clause OrderByClause orderbyOption = null; if (tokenIn.OrderByOptions != null) { MetadataBinder binder = this.BuildNewMetadataBinder(targetNavigationSource, generatedProperties, collapsed); OrderByBinder orderByBinder = new OrderByBinder(binder.Bind); orderbyOption = orderByBinder.BindOrderBy(binder.BindingState, tokenIn.OrderByOptions); } SearchClause searchOption = null; if (tokenIn.SearchOption != null) { MetadataBinder binder = this.BuildNewMetadataBinder(targetNavigationSource); SearchBinder searchBinder = new SearchBinder(binder.Bind); searchOption = searchBinder.BindSearch(tokenIn.SearchOption); } if (isRef) { return(new ExpandedReferenceSelectItem(pathToNavProp, targetNavigationSource, filterOption, orderbyOption, tokenIn.TopOption, tokenIn.SkipOption, tokenIn.CountQueryOption, searchOption, computeOption, applyOption)); } SelectExpandClause subSelectExpand; if (tokenIn.ExpandOption != null) { subSelectExpand = this.GenerateSubExpand(tokenIn); } else { subSelectExpand = BuildDefaultSubExpand(); } subSelectExpand = this.DecorateExpandWithSelect(subSelectExpand, currentNavProp, tokenIn.SelectOption, this.CreateBindingState(targetNavigationSource, generatedProperties, collapsed)); LevelsClause levelsOption = ParseLevels(tokenIn.LevelsOption, currentLevelEntityType, currentNavProp); return(new ExpandedNavigationSelectItem(pathToNavProp, targetNavigationSource, subSelectExpand, filterOption, orderbyOption, tokenIn.TopOption, tokenIn.SkipOption, tokenIn.CountQueryOption, searchOption, levelsOption, computeOption, applyOption)); }
/// <summary> /// Asynchronously creates an <see cref="ODataReader" /> to read a resource set in a Uri operation parameter. /// </summary> /// <param name="entitySet">The entity set we are going to read resources for.</param> /// <param name="expectedResourceType">The expected structured type for the items in the resource set.</param> /// <returns>Task which when completed returns the newly created <see cref="ODataReader"/>.</returns> public virtual Task <ODataReader> CreateUriParameterResourceSetReaderAsync(IEdmEntitySetBase entitySet, IEdmStructuredType expectedResourceType) { throw this.CreatePayloadKindNotSupportedException(ODataPayloadKind.ResourceSet); }
/// <inheritdoc /> public bool AppliesToAction(ODataControllerActionContext context) { if (context == null) { throw Error.ArgumentNull(nameof(context)); } Debug.Assert(context.Action != null); ActionModel action = context.Action; string actionMethodName = action.ActionMethod.Name; // Need to refactor the following // for example: CreateRef( with the navigation property parameter) should for all navigation properties // CreateRefToOrdersFromCustomer, CreateRefToOrders, CreateRef. string method = SplitRefActionName(actionMethodName, out string httpMethod, out string property, out string declaring); if (method == null) { return(false); } // Action parameter should have a (string navigationProperty) parameter if (!action.HasParameter <string>("navigationProperty")) { return(false); } IEdmNavigationSource navigationSource; IEdmEntityType entityType; if (context.EntitySet != null) { entityType = context.EntitySet.EntityType(); navigationSource = context.EntitySet; } else { entityType = context.Singleton.EntityType(); navigationSource = context.Singleton; } // For entity set, we should have the key parameter // For Singleton, we should not have the key parameter bool hasODataKeyParameter = action.HasODataKeyParameter(entityType); if ((context.EntitySet != null && !hasODataKeyParameter) || (context.Singleton != null && hasODataKeyParameter)) { return(false); } // Find the navigation property declaring type IEdmStructuredType declaringType = entityType; if (declaring != null) { declaringType = entityType.FindTypeInInheritance(context.Model, declaring); if (declaringType == null) { return(false); } } // Find the navigation property if have IEdmNavigationProperty navigationProperty = null; if (property != null) { navigationProperty = declaringType.DeclaredNavigationProperties().FirstOrDefault(p => p.Name == property); } if (navigationProperty == null) { return(false); } IList <ODataSegmentTemplate> segments = new List <ODataSegmentTemplate>(); if (context.EntitySet != null) { segments.Add(new EntitySetSegmentTemplate(context.EntitySet)); segments.Add(KeySegmentTemplate.CreateKeySegment(entityType, context.EntitySet)); } else { segments.Add(new SingletonSegmentTemplate(context.Singleton)); } if (entityType != declaringType) { segments.Add(new CastSegmentTemplate(declaringType, entityType, navigationSource)); } IEdmNavigationSource targetNavigationSource = navigationSource.FindNavigationTarget(navigationProperty, segments, out _); if (navigationProperty != null) { segments.Add(new NavigationSegmentTemplate(navigationProperty, targetNavigationSource)); } else { //TODO: Add the navigation template segment template, // Or add the template for all navigation properties? return(false); } IEdmEntityType navigationPropertyType = navigationProperty.Type.GetElementTypeOrSelf().AsEntity().EntityDefinition(); bool hasNavigationPropertyKeyParameter = action.HasODataKeyParameter(navigationPropertyType, "relatedKey"); if (hasNavigationPropertyKeyParameter) { segments.Add(KeySegmentTemplate.CreateKeySegment(navigationPropertyType, targetNavigationSource, "relatedKey")); } segments.Add(new RefSegmentTemplate(navigationProperty, targetNavigationSource)); // TODO: support key as segment? ODataPathTemplate template = new ODataPathTemplate(segments); action.AddSelector(httpMethod, context.Prefix, context.Model, template, context.RouteOptions); // processed return(true); }
/// <summary> /// Asynchronously creates an <see cref="ODataReader" /> to read a resource in a Uri operation parameter. /// </summary> /// <param name="navigationSource">The navigation source we are going to read resources for.</param> /// <param name="expectedResourceType">The expected structured type for the resource to be read.</param> /// <returns>Task which when completed returns the newly created <see cref="ODataReader"/>.</returns> public virtual Task <ODataReader> CreateUriParameterResourceReaderAsync(IEdmNavigationSource navigationSource, IEdmStructuredType expectedResourceType) { throw this.CreatePayloadKindNotSupportedException(ODataPayloadKind.Parameter); }
/// <summary> /// Build a segment from a token. /// </summary> /// <param name="tokenIn">the token to bind</param> /// <param name="model">The model.</param> /// <param name="edmType">the type of the current scope based on type segments.</param> /// <param name="resolver">Resolver for uri parser.</param> /// <param name="state">The binding state.</param> /// <returns>The segment created from the token.</returns> public static ODataPathSegment ConvertNonTypeTokenToSegment(PathSegmentToken tokenIn, IEdmModel model, IEdmStructuredType edmType, ODataUriResolver resolver, BindingState state = null) { ExceptionUtils.CheckArgumentNotNull(resolver, "resolver"); ODataPathSegment nextSegment; if (UriParserHelper.IsAnnotation(tokenIn.Identifier)) { if (TryBindAsDeclaredTerm(tokenIn, model, resolver, out nextSegment)) { return(nextSegment); } string qualifiedTermName = tokenIn.Identifier.Remove(0, 1); int separator = qualifiedTermName.LastIndexOf(".", StringComparison.Ordinal); string namespaceName = qualifiedTermName.Substring(0, separator); string termName = qualifiedTermName.Substring(separator == 0 ? 0 : separator + 1); // Don't allow selecting odata control information if (String.Compare(namespaceName, ODataConstants.ODataPrefix, StringComparison.OrdinalIgnoreCase) == 0) { throw new ODataException(ODataErrorStrings.UriSelectParser_TermIsNotValid(tokenIn.Identifier)); } return(new AnnotationSegment(new EdmTerm(namespaceName, termName, EdmCoreModel.Instance.GetUntyped()))); } EndPathToken endPathToken = new EndPathToken(tokenIn.Identifier, null); if ((state?.IsCollapsed ?? false) && !(state?.AggregatedPropertyNames?.Contains(endPathToken) ?? false)) { throw new ODataException(ODataErrorStrings.ApplyBinder_GroupByPropertyNotPropertyAccessValue(tokenIn.Identifier)); } if (TryBindAsDeclaredProperty(tokenIn, edmType, resolver, out nextSegment)) { return(nextSegment); } // Operations must be container-qualified, and because the token type indicates it was not a .-separated identifier, we should not try to look up operations. if (tokenIn.IsNamespaceOrContainerQualified()) { if (TryBindAsOperation(tokenIn, model, edmType, out nextSegment)) { return(nextSegment); } // If an action or function is requested in a selectItem using a qualifiedActionName or a qualifiedFunctionName // and that operation cannot be bound to the entities requested, the service MUST ignore the selectItem. if (!edmType.IsOpen) { return(null); } } if (edmType.IsOpen || (state?.AggregatedPropertyNames?.Contains(endPathToken) ?? false)) { return(new DynamicPathSegment(tokenIn.Identifier)); } throw new ODataException(ODataErrorStrings.MetadataBinder_PropertyNotDeclared(edmType.FullTypeName(), tokenIn.Identifier)); }
/// <summary> /// Verifies that CreateResourceReader, CreateResourceSetReader, CreateDeltaResourceSetReader or CreateDeltaReader can be called. /// </summary> /// <param name="navigationSource">The navigation source we are going to read resources for.</param> /// <param name="structuredType">The expected structured type for the resource/resource set to be read.</param> private void VerifyCanCreateODataReader(IEdmNavigationSource navigationSource, IEdmStructuredType structuredType) { Debug.Assert(navigationSource == null || structuredType != null, "If an navigation source is specified, the structured type must be specified as well."); // We require metadata information for reading requests. if (!this.ReadingResponse) { this.VerifyUserModel(); // TODO: check for entity only if (navigationSource == null && (structuredType != null && structuredType.IsODataEntityTypeKind())) { throw new ODataException(ODataErrorStrings.ODataJsonLightInputContext_NoEntitySetForRequest); } } // We only check that the base type of the entity set is assignable from the specified entity type. // If no resource set/resource type is specified in the API, we will read it from the context URI. IEdmEntityType entitySetElementType = this.EdmTypeResolver.GetElementType(navigationSource); if (navigationSource != null && structuredType != null && !structuredType.IsOrInheritsFrom(entitySetElementType)) { throw new ODataException(ODataErrorStrings.ODataJsonLightInputContext_EntityTypeMustBeCompatibleWithEntitySetBaseType(structuredType.FullTypeName(), entitySetElementType.FullName(), navigationSource.FullNavigationSourceName())); } }
/// <summary> /// Creates an <see cref="ODataReader" /> to read a resource set. /// </summary> /// <param name="entitySet">The entity set we are going to read resources for.</param> /// <param name="expectedResourceType">The expected structured type for the items in the resource set.</param> /// <param name="readingParameter">true means reading a resource set in uri operation parameter, false reading a resource set in other payloads.</param> /// <param name="readingDelta">true if reading a delta resource set.</param> /// <returns>The newly created <see cref="ODataReader"/>.</returns> private ODataReader CreateResourceSetReaderImplementation(IEdmEntitySetBase entitySet, IEdmStructuredType expectedResourceType, bool readingParameter, bool readingDelta) { return(new ODataJsonLightReader(this, entitySet, expectedResourceType, /*readingResourceSet*/ true, readingParameter, readingDelta)); }
/// <summary> /// Asynchronously creates an <see cref="ODataReader" /> to read a resource. /// </summary> /// <param name="navigationSource">The navigation source we are going to read resources for.</param> /// <param name="expectedResourceType">The expected structured type for the resource to be read.</param> /// <returns>Task which when completed returns the newly created <see cref="ODataReader"/>.</returns> public override Task <ODataReader> CreateResourceReaderAsync(IEdmNavigationSource navigationSource, IEdmStructuredType expectedResourceType) { this.AssertAsynchronous(); this.VerifyCanCreateODataReader(navigationSource, expectedResourceType); // Note that the reading is actually synchronous since we buffer the entire input when getting the stream from the message. return(TaskUtils.GetTaskForSynchronousOperation(() => this.CreateResourceReaderImplementation(navigationSource, expectedResourceType))); }
/// <summary> /// Gets a resource metadata builder for the given resource. /// </summary> /// <param name="resourceState">Resource state to use as reference for information needed by the builder.</param> /// <param name="useKeyAsSegment">true if keys should go in separate segments in auto-generated URIs, false if they should go in parentheses.</param> /// <returns>A resource metadata builder.</returns> public ODataResourceMetadataBuilder GetResourceMetadataBuilderForReader(IODataJsonLightReaderResourceState resourceState, bool useKeyAsSegment) { Debug.Assert(resourceState != null, "resource != null"); // Only apply the conventional template builder on response. On a request we would only report what's on the wire. if (resourceState.MetadataBuilder == null) { ODataResourceBase resource = resourceState.Resource; if (this.isResponse) { ODataTypeAnnotation typeAnnotation = resource.TypeAnnotation; IEdmStructuredType structuredType = null; if (typeAnnotation != null) { if (typeAnnotation.Type != null) { // First try ODataTypeAnnotation.Type (for perf improvement) structuredType = typeAnnotation.Type as IEdmStructuredType; } else if (typeAnnotation.TypeName != null) { // Then try ODataTypeAnnotation.TypeName structuredType = this.model.FindType(typeAnnotation.TypeName) as IEdmStructuredType; } } if (structuredType == null) { // No type name read from the payload. Use resource type from model. structuredType = resourceState.ResourceType; } IEdmNavigationSource navigationSource = resourceState.NavigationSource; IEdmEntityType navigationSourceElementType = this.edmTypeResolver.GetElementType(navigationSource); IODataResourceTypeContext typeContext = ODataResourceTypeContext.Create( /*serializationInfo*/ null, navigationSource, navigationSourceElementType, resourceState.ResourceTypeFromMetadata ?? resourceState.ResourceType, /*throwIfMissingTypeInfo*/ true); IODataResourceMetadataContext resourceMetadataContext = ODataResourceMetadataContext.Create(resource, typeContext, /*serializationInfo*/ null, structuredType, this, resourceState.SelectedProperties); ODataConventionalUriBuilder uriBuilder = new ODataConventionalUriBuilder(this.ServiceBaseUri, useKeyAsSegment ? ODataUrlKeyDelimiter.Slash : ODataUrlKeyDelimiter.Parentheses); if (structuredType.IsODataEntityTypeKind()) { resourceState.MetadataBuilder = new ODataConventionalEntityMetadataBuilder(resourceMetadataContext, this, uriBuilder); } else { resourceState.MetadataBuilder = new ODataConventionalResourceMetadataBuilder(resourceMetadataContext, this, uriBuilder); } } else { resourceState.MetadataBuilder = new NoOpResourceMetadataBuilder(resource); } } return(resourceState.MetadataBuilder); }
public TestEdmStructuredObject(IEdmStructuredType edmType) : base(edmType) { }
/// <summary> /// Creates an <see cref="ODataReader" /> to read a resource set in a Uri operation parameter. /// </summary> /// <param name="entitySet">The entity set we are going to read resources for.</param> /// <param name="expectedResourceType">The expected structured type for the items in the resource set.</param> /// <returns>The newly created <see cref="ODataReader"/>.</returns> public override ODataReader CreateUriParameterResourceSetReader(IEdmEntitySetBase entitySet, IEdmStructuredType expectedResourceType) { this.AssertSynchronous(); this.VerifyCanCreateODataReader(entitySet, expectedResourceType); return(this.CreateResourceSetReaderImplementation(entitySet, expectedResourceType, /*readingParameter*/ true, /*readingDelta*/ false)); }
/// <summary> /// Write the given collection of properties. /// </summary> /// <param name="owningType">The <see cref="IEdmStructuredType"/> of the entry (or null if not metadata is available).</param> /// <param name="cachedProperties">Collection of cached properties for the entry.</param> /// <param name="isWritingCollection">true if we are writing a top level collection instead of an entry.</param> /// <param name="beforePropertiesAction">Action which is called before the properties are written, if there are any property.</param> /// <param name="afterPropertiesAction">Action which is called after the properties are written, if there are any property.</param> /// <param name="duplicatePropertyNamesChecker">The checker instance for duplicate property names.</param> /// <param name="projectedProperties">Set of projected properties, or null if all properties should be written.</param> /// <returns>true if anything was written, false otherwise.</returns> internal bool WriteProperties( IEdmStructuredType owningType, IEnumerable<ODataProperty> cachedProperties, bool isWritingCollection, Action beforePropertiesAction, Action afterPropertiesAction, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, ProjectedPropertiesAnnotation projectedProperties) { if (cachedProperties == null) { return false; } bool propertyWritten = false; foreach (ODataProperty property in cachedProperties) { propertyWritten |= this.WriteProperty( property, owningType, /*isTopLevel*/false, isWritingCollection, propertyWritten ? null : beforePropertiesAction, duplicatePropertyNamesChecker, projectedProperties); } if (afterPropertiesAction != null && propertyWritten) { afterPropertiesAction(); } return propertyWritten; }
/// <summary> /// Asynchronously creates an <see cref="ODataReader" /> to read a resource set in a Uri operation parameter. /// </summary> /// <param name="entitySet">The entity set we are going to read resources for.</param> /// <param name="expectedResourceType">The expected structured type for the items in the resource set.</param> /// <returns>Task which when completed returns the newly created <see cref="ODataReader"/>.</returns> public override Task <ODataReader> CreateUriParameterResourceSetReaderAsync(IEdmEntitySetBase entitySet, IEdmStructuredType expectedResourceType) { this.AssertAsynchronous(); this.VerifyCanCreateODataReader(entitySet, expectedResourceType); return(TaskUtils.GetTaskForSynchronousOperation(() => this.CreateResourceSetReaderImplementation(entitySet, expectedResourceType, /*readingParameter*/ true, /*readingDelta*/ false))); }
public static PropertyInfo GetDynamicPropertyDictionary(IEdmStructuredType edmType, IEdmModel edmModel) { if (edmType == null) { throw Error.ArgumentNull("edmType"); } if (edmModel == null) { throw Error.ArgumentNull("edmModel"); } DynamicPropertyDictionaryAnnotation annotation = edmModel.GetAnnotationValue<DynamicPropertyDictionaryAnnotation>(edmType); if (annotation != null) { return annotation.PropertyInfo; } return null; }
/// <summary> /// Asynchronously creates an <see cref="ODataReader" /> to read a resource in a Uri operation parameter. /// </summary> /// <param name="navigationSource">The navigation source we are going to read resources for.</param> /// <param name="expectedResourceType">The expected structured type for the resource to be read.</param> /// <returns>Task which when completed returns the newly created <see cref="ODataReader"/>.</returns> public override Task <ODataReader> CreateUriParameterResourceReaderAsync(IEdmNavigationSource navigationSource, IEdmStructuredType expectedResourceType) { return(this.CreateResourceReaderAsync(navigationSource, expectedResourceType)); }