public CsdlSemanticsNavigationSource(CsdlSemanticsEntityContainer container, CsdlAbstractNavigationSource navigationSource) : base(navigationSource) { this.container = container; this.navigationSource = navigationSource; this.path = new EdmPathExpression(this.navigationSource.Name); }
public static IEdmNavigationSource FindNavigationTarget(this IEdmNavigationSource navigationSource, IEdmNavigationProperty navigationProperty, IList <ODataSegmentTemplate> parsedSegments, out IEdmPathExpression bindingPath) { bindingPath = null; if (navigationProperty.ContainsTarget) { return(navigationSource); } IEnumerable <IEdmNavigationPropertyBinding> bindings = navigationSource.FindNavigationPropertyBindings(navigationProperty); if (bindings != null) { foreach (var binding in bindings) { if (BindingPathHelper.MatchBindingPath(binding.Path, parsedSegments)) { bindingPath = binding.Path; return(binding.Target); } } } return(null); }
private OdcmProperty PropertyFromPathExpression(IEdmPathExpression pathExpression, OdcmObject odcmObject) { OdcmClass odcmClass = null; if (odcmObject is OdcmProperty) { var odcmProperty = odcmObject as OdcmProperty; odcmClass = odcmProperty.Type as OdcmClass; } else { odcmClass = odcmObject as OdcmClass; } var pathBuilder = new StringBuilder(); foreach (var path in pathExpression.Path) { pathBuilder.AppendFormat("{0}.", path); } pathBuilder.Remove(pathBuilder.Length - 1, 1); OdcmProperty navProperty; if (!odcmClass.TryFindProperty(pathBuilder.ToString(), out navProperty)) { throw new InvalidOperationException( string.Format( "Unable to find property {0} in class {1}. This can be caused by malformed Capability Annotation on an EntitySet", pathBuilder.ToString(), odcmClass.FullName)); } return(navProperty); }
internal static bool TryAssertPathAsType(this IEdmPathExpression expression, IEdmTypeReference type, IEdmType context, bool matchExactly, out IEnumerable <EdmError> discoveredErrors) { IEdmStructuredType structuredContext = context as IEdmStructuredType; if (structuredContext != null) { IEdmType result = context; foreach (string segment in expression.Path) { IEdmStructuredType structuredResult = result as IEdmStructuredType; if (structuredResult == null) { discoveredErrors = new EdmError[] { new EdmError(expression.Location(), EdmErrorCode.PathIsNotValidForTheGivenContext, Edm.Strings.EdmModel_Validator_Semantic_PathIsNotValidForTheGivenContext(segment)) }; return(false); } IEdmProperty resultProperty = structuredResult.FindProperty(segment); result = (resultProperty != null) ? resultProperty.Type.Definition : null; // If the path is not resolved, it could refer to an open type, and we cannot make an assertion about its type. if (result == null) { discoveredErrors = Enumerable.Empty <EdmError>(); return(true); } } return(TestTypeMatch(result, type.Definition, expression.Location(), matchExactly, out discoveredErrors)); } discoveredErrors = Enumerable.Empty <EdmError>(); return(true); }
public static bool MatchBindingPath(IEdmPathExpression bindingPath, IList <ODataSegmentTemplate> parsedSegments) { List <string> paths = bindingPath.PathSegments.ToList(); // If binding path only includes navigation property name, it matches. if (paths.Count == 1) { return(true); } int pathIndex = paths.Count - 2; // Skip the last segment which is navigation property name. // Match from tail to head. for (int segmentIndex = parsedSegments.Count - 1; segmentIndex >= 0; segmentIndex--) { ODataSegmentTemplate segment = parsedSegments[segmentIndex]; PropertySegmentTemplate propertySegment = segment as PropertySegmentTemplate; NavigationSegmentTemplate navigationSegment = segment as NavigationSegmentTemplate; // Containment navigation property or complex property in binding path. if (propertySegment != null || (navigationSegment != null && navigationSegment.Segment.NavigationSource is IEdmContainedEntitySet)) { string pathName = propertySegment != null ? propertySegment.Property.Name : navigationSegment.NavigationProperty.Name; if (pathIndex < 0 || string.CompareOrdinal(paths[pathIndex], pathName) != 0) { return(false); } pathIndex--; } else if (segment is CastSegmentTemplate) { CastSegmentTemplate cast = (CastSegmentTemplate)segment; // May need match type if the binding path contains type cast. if (pathIndex >= 0 && paths[pathIndex].Contains(".", System.StringComparison.Ordinal)) { if (string.CompareOrdinal(paths[pathIndex], cast.CastType.AsElementType().FullTypeName()) != 0) { return(false); } pathIndex--; } } else if (segment is EntitySetSegmentTemplate || segment is SingletonSegmentTemplate || navigationSegment != null) { // Containment navigation property in first if statement for NavigationPropertySegment. break; } } // Return true if all the segments in binding path have been matched. return(pathIndex == -1 ? true : false); }
public static IEnumerable <IEdmStructuralProperty> GetConcurrencyProperties(this IEdmModel model, IEdmNavigationSource navigationSource) { Contract.Assert(model != null); Contract.Assert(navigationSource != null); IEnumerable <IEdmStructuralProperty> cachedProperties; if (_concurrencyProperties != null && _concurrencyProperties.TryGetValue(navigationSource, out cachedProperties)) { return(cachedProperties); } IList <IEdmStructuralProperty> results = new List <IEdmStructuralProperty>(); IEdmEntityType entityType = navigationSource.EntityType(); IEdmVocabularyAnnotatable annotatable = navigationSource as IEdmVocabularyAnnotatable; IEdmContainedEntitySet navigationSourceAsEntitySet = navigationSource as IEdmContainedEntitySet; if (navigationSourceAsEntitySet != null) { annotatable = navigationSourceAsEntitySet.NavigationProperty as EdmNavigationProperty; } if (annotatable != null) { IEdmValueAnnotation annotation = model.FindVocabularyAnnotations <IEdmValueAnnotation>(annotatable, CoreVocabularyModel.ConcurrencyTerm).FirstOrDefault(); if (annotation != null) { IEdmCollectionExpression properties = annotation.Value as IEdmCollectionExpression; if (properties != null) { foreach (var property in properties.Elements) { IEdmPathExpression pathExpression = property as IEdmPathExpression; if (pathExpression != null) { // So far, we only consider the single path, because only the direct properties from declaring type are used. // However we have an issue tracking on: https://github.com/OData/WebApi/issues/472 string propertyName = pathExpression.Path.Single(); IEdmProperty edmProperty = entityType.FindProperty(propertyName); IEdmStructuralProperty structuralProperty = edmProperty as IEdmStructuralProperty; if (structuralProperty != null) { results.Add(structuralProperty); } } } } } } if (_concurrencyProperties == null) { _concurrencyProperties = new ConcurrentDictionary <IEdmNavigationSource, IEnumerable <IEdmStructuralProperty> >(); } _concurrencyProperties[navigationSource] = results; return(results); }
private OdcmProperty SetPathCapability(OdcmObject odcmObject, IEdmPathExpression expression, string annotationTerm) { var odcmProperty = PropertyFromPathExpression(expression, odcmObject); // The term name serves as a tag for this capability SetBooleanCapability(odcmProperty, false, annotationTerm); return(odcmProperty); }
/// <summary> /// Sets the partner information. /// </summary> /// <param name="navigationProperty">The partner navigation property.</param> /// <param name="navigationPropertyPath">Path to the partner navigation property in the related entity type.</param> internal void SetPartner(IEdmNavigationProperty navigationProperty, IEdmPathExpression navigationPropertyPath) { Debug.Assert( DeclaringType is IEdmEntityType, "Partner info cannot be set for nav. property on a non-entity type."); partner = navigationProperty; PartnerPath = navigationPropertyPath; }
private static void AddProcedures(this EdmModel model, IEnumerable <ProcedureConfiguration> configurations, EdmEntityContainer container, Dictionary <Type, IEdmType> edmTypeMap, IDictionary <string, EdmNavigationSource> edmNavigationSourceMap) { Contract.Assert(model != null, "Model can't be null"); ValidateActionOverload(configurations.OfType <ActionConfiguration>()); foreach (ProcedureConfiguration procedure in configurations) { IEdmTypeReference returnReference = GetEdmTypeReference( edmTypeMap, procedure.ReturnType, procedure.ReturnType != null && EdmLibHelpers.IsNullable(procedure.ReturnType.ClrType)); IEdmExpression expression = GetEdmEntitySetExpression(edmNavigationSourceMap, procedure); IEdmPathExpression pathExpression = procedure.EntitySetPath != null ? new EdmPathExpression(procedure.EntitySetPath) : null; EdmOperationImport operationImport; switch (procedure.Kind) { case ProcedureKind.Action: operationImport = CreateActionImport(procedure, container, returnReference, expression, pathExpression); break; case ProcedureKind.Function: operationImport = CreateFunctionImport((FunctionConfiguration)procedure, container, returnReference, expression, pathExpression); break; case ProcedureKind.ServiceOperation: Contract.Assert(false, "ServiceOperations are not supported."); goto default; default: Contract.Assert(false, "Unsupported ProcedureKind"); return; } EdmOperation operation = (EdmOperation)operationImport.Operation; if (procedure.IsBindable && procedure.Title != null & procedure.Title != procedure.Name) { model.SetOperationTitleAnnotation(operation, new OperationTitleAnnotation(procedure.Title)); } AddProcedureParameters(operation, procedure, edmTypeMap); if (procedure.IsBindable) { AddProcedureLinkBuilder(model, operation, procedure); ValidateProcedureEntitySetPath(model, operationImport, procedure); } else { container.AddElement(operationImport); } model.AddElement(operation); } }
/// <summary> /// Initializes a new instance of the <see cref="EdmEntitySet"/> class. /// </summary> /// <param name="container">An <see cref="IEdmEntityContainer"/> containing this entity set.</param> /// <param name="name">Name of the entity set.</param> /// <param name="elementType">The entity type of the elements in this entity set.</param> public EdmEntitySet(IEdmEntityContainer container, string name, IEdmEntityType elementType) : base(name, elementType) { EdmUtil.CheckArgumentNull(container, "container"); this.container = container; this.type = new EdmCollectionType(new EdmEntityTypeReference(elementType, false)); this.path = new EdmPathExpression(this.container.FullName() + "." + this.Name); }
public static IEnumerable <IEdmStructuralProperty> GetConcurrencyProperties(this IEdmModel model, IEdmNavigationSource navigationSource) { Contract.Assert(model != null); Contract.Assert(navigationSource != null); // Ensure that concurrency properties cache is attached to model as an annotation to avoid expensive calculations each time ConcurrencyPropertiesAnnotation concurrencyProperties = model.GetAnnotationValue <ConcurrencyPropertiesAnnotation>(model); if (concurrencyProperties == null) { concurrencyProperties = new ConcurrencyPropertiesAnnotation(); model.SetAnnotationValue(model, concurrencyProperties); } IEnumerable <IEdmStructuralProperty> cachedProperties; if (concurrencyProperties.TryGetValue(navigationSource, out cachedProperties)) { return(cachedProperties); } IList <IEdmStructuralProperty> results = new List <IEdmStructuralProperty>(); IEdmEntityType entityType = navigationSource.EntityType(); IEdmVocabularyAnnotatable annotatable = navigationSource as IEdmVocabularyAnnotatable; if (annotatable != null) { var annotations = model.FindVocabularyAnnotations <IEdmVocabularyAnnotation>(annotatable, CoreVocabularyModel.ConcurrencyTerm); IEdmVocabularyAnnotation annotation = annotations.FirstOrDefault(); if (annotation != null) { IEdmCollectionExpression properties = annotation.Value as IEdmCollectionExpression; if (properties != null) { foreach (var property in properties.Elements) { IEdmPathExpression pathExpression = property as IEdmPathExpression; if (pathExpression != null) { // So far, we only consider the single path, because only the direct properties from declaring type are used. // However we have an issue tracking on: https://github.com/OData/WebApi/issues/472 string propertyName = pathExpression.PathSegments.First(); IEdmProperty edmProperty = entityType.FindProperty(propertyName); IEdmStructuralProperty structuralProperty = edmProperty as IEdmStructuralProperty; if (structuralProperty != null) { results.Add(structuralProperty); } } } } } } concurrencyProperties[navigationSource] = results; return(results); }
/// <summary> /// Initializes a new instance of the <see cref="EdmEntitySet"/> class. /// </summary> /// <param name="container">An <see cref="IEdmEntityContainer"/> containing this entity set.</param> /// <param name="name">Name of the entity set.</param> /// <param name="elementType">The entity type of the elements in this entity set.</param> public EdmEntitySet(IEdmEntityContainer container, string name, IEdmEntityType elementType) : this(container, name, elementType, true) { EdmUtil.CheckArgumentNull(container, "container"); this.container = container; this.type = new EdmCollectionType(new EdmEntityTypeReference(elementType, false)); this.path = new EdmPathExpression(this.container.FullName() + "." + this.Name); }
/// <summary> /// Determine if the path of current navigation property is matching the binding path. /// The function used in FindNavigationTarget to resolve the navigation target for multi binding. /// </summary> /// <param name="bindingPath">The binding path.</param> /// <param name="parsedSegments">The list of segments in Uri path.</param> /// <returns>True if the path of navigation property in current scope is matching the <paramref name="bindingPath"/>.</returns> public static bool MatchBindingPath(IEdmPathExpression bindingPath, IList <ODataPathSegment> parsedSegments) { List <string> paths = bindingPath.PathSegments.ToList(); // If binding path only includes navigation property name, it matches. if (paths.Count == 1) { return(true); } int pathIndex = paths.Count - 2; // Skip the last segment which is navigation property name. int segmentIndex = parsedSegments.Count - 1; // Match from tail to head. for (; segmentIndex >= 0; segmentIndex--) { ODataPathSegment segment = parsedSegments[segmentIndex]; // Cache the cast result to avoid CA1800:DoNotCastUnnecessarily. bool segmentIsNavigationPropertySegment = segment is NavigationPropertySegment; // Containment navigation property or complex property in binding path. if (segment is PropertySegment || (segmentIsNavigationPropertySegment && segment.TargetEdmNavigationSource is IEdmContainedEntitySet)) { if (pathIndex < 0 || string.CompareOrdinal(paths[pathIndex], segment.Identifier) != 0) { return(false); } pathIndex--; } else if (segment is TypeSegment) { // May need match type if the binding path contains type cast. if (pathIndex >= 0 && paths[pathIndex].IndexOf('.') >= 0) { if (string.CompareOrdinal(paths[pathIndex], segment.EdmType.AsElementType().FullTypeName()) != 0) { return(false); } pathIndex--; } } else if (segmentIsNavigationPropertySegment || segment is EntitySetSegment || segment is SingletonSegment) { // Containment navigation property in first if statement for NavigationPropertySegment. break; } } // Return true if all the segments in binding path have been matched. return(pathIndex == -1 ? true : false); }
public CsdlNavigationProperty(string name, string type, bool?nullable, string partner, bool containsTarget, CsdlOnDelete onDelete, IEnumerable <CsdlReferentialConstraint> referentialConstraints, CsdlDocumentation documentation, CsdlLocation location) : base(name, documentation, location) { this.type = type; this.nullable = nullable; this.partnerPath = partner == null ? null : new EdmPathExpression(partner); this.containsTarget = containsTarget; this.onDelete = onDelete; this.referentialConstraints = referentialConstraints; }
/// <summary> /// Initializes a new instance of the <see cref="EdmSingleton"/> class. /// </summary> /// <param name="container">An <see cref="IEdmEntityContainer"/> containing this entity set.</param> /// <param name="name">Name of the singleton.</param> /// <param name="entityType">The entity type of the element of this singleton.</param> public EdmSingleton(IEdmEntityContainer container, string name, IEdmEntityType entityType) : base(name) { EdmUtil.CheckArgumentNull(container, "container"); EdmUtil.CheckArgumentNull(entityType, "entityType"); this.container = container; this.entityType = entityType; this.path = new EdmPathExpression(name); }
/// <summary> /// Initializes a new instance of the <see cref="EdmContainedEntitySet"/> class. /// </summary> /// <param name="parentNavigationSource">The <see cref="IEdmNavigationSource"/> that container element belongs to</param> /// <param name="navigationProperty">An <see cref="IEdmNavigationProperty"/> containing the navigation property definition of the contained element</param> /// <param name="navigationPath">The path from the parentNavigationSource to the related resource, concluding with the navigation property name. May traverse complex types and cast segments</param> public EdmContainedEntitySet(IEdmNavigationSource parentNavigationSource, IEdmNavigationProperty navigationProperty, IEdmPathExpression navigationPath) : base(navigationProperty.Name, navigationProperty.ToEntityType()) { EdmUtil.CheckArgumentNull(parentNavigationSource, "parentNavigationSource"); EdmUtil.CheckArgumentNull(navigationProperty, "navigationProperty"); this.parentNavigationSource = parentNavigationSource; this.navigationProperty = navigationProperty; this.navigationPath = navigationPath; }
/// <summary> /// Initializes a new instance of the <see cref="EdmEntitySet"/> class. /// </summary> /// <param name="container">An <see cref="IEdmEntityContainer"/> containing this entity set.</param> /// <param name="name">Name of the entity set.</param> /// <param name="elementType">The entity type of the elements in this entity set.</param> /// <param name="includeInServiceDocument">Indicates whether the entity set is advertised in the service document.</param> public EdmEntitySet(IEdmEntityContainer container, string name, IEdmEntityType elementType, bool includeInServiceDocument) : base(name, elementType) { EdmUtil.CheckArgumentNull(container, "container"); this.container = container; this.type = new EdmCollectionType(new EdmEntityTypeReference(elementType, false)); this.path = new EdmPathExpression(this.container.FullName() + "." + this.Name); this.includeInServiceDocument = includeInServiceDocument; }
public IEdmNavigationSource FindNavigationTarget(IEdmNavigationProperty navigationProperty) { bool isDerived = !this.Type.AsElementType().IsOrInheritsFrom(navigationProperty.DeclaringType); IEdmPathExpression bindingPath = isDerived ? new EdmPathExpression(navigationProperty.DeclaringType.FullTypeName(), navigationProperty.Name) : new EdmPathExpression(navigationProperty.Name); return(FindNavigationTarget(navigationProperty, bindingPath)); }
/// <summary> /// Initializes a new instance of the <see cref="EdmAction"/> class. /// </summary> /// <param name="namespaceName">Name of the namespace.</param> /// <param name="name">The name.</param> /// <param name="returnType">Type of the return.</param> /// <param name="isBound">if set to <c>true</c> [is bound].</param> /// <param name="entitySetPathExpression">The entity set path expression.</param> protected EdmOperation(string namespaceName, string name, IEdmTypeReference returnType, bool isBound, IEdmPathExpression entitySetPathExpression) : base(name) { EdmUtil.CheckArgumentNull(namespaceName, "namespaceName"); this.ReturnType = returnType; this.Namespace = namespaceName; this.IsBound = isBound; this.EntitySetPath = entitySetPathExpression; }
/// <summary> /// Finds the navigation source that a navigation property targets. /// </summary> /// <param name="navigationProperty">The navigation property.</param> /// <returns>The navigation source that the navigation proportion targets, or null if no such navigation source exists.</returns> public virtual IEdmNavigationSource FindNavigationTarget(IEdmNavigationProperty navigationProperty) { EdmUtil.CheckArgumentNull(navigationProperty, "property"); bool isDerived = !(navigationProperty.DeclaringType.AsElementType() is IEdmComplexType) && !this.Type.AsElementType().IsOrInheritsFrom(navigationProperty.DeclaringType); IEdmPathExpression bindingPath = isDerived ? new EdmPathExpression(navigationProperty.DeclaringType.FullTypeName(), navigationProperty.Name) : new EdmPathExpression(navigationProperty.Name); return(FindNavigationTarget(navigationProperty, bindingPath)); }
public void SetNavigationPropertyPartner( EdmNavigationProperty navigationProperty, IEdmPathExpression navigationPropertyPath, EdmNavigationProperty partnerNavigationProperty, IEdmPathExpression partnerNavigationPropertyPath) { Debug.Assert( this.IsOnSameTypeHierarchyLineWith(navigationProperty.DeclaringType), "Nav. property is not defined on this or a derived entity type."); navigationProperty.SetPartner(partnerNavigationProperty, partnerNavigationPropertyPath); if (partnerNavigationProperty.DeclaringType is IEdmEntityType) { partnerNavigationProperty.SetPartner(navigationProperty, navigationPropertyPath); } }
private static EdmOperationImport CreateActionImport( OperationConfiguration operationConfiguration, EdmEntityContainer container, IEdmTypeReference returnReference, IEdmExpression expression, IEdmPathExpression pathExpression) { EdmAction operation = new EdmAction( operationConfiguration.Namespace, operationConfiguration.Name, returnReference, operationConfiguration.IsBindable, pathExpression); return(new EdmActionImport(container, operationConfiguration.Name, operation, expression)); }
/// <summary> /// Constructs a SingleNavigationNode. /// </summary> /// <param name="navigationSource">The navigation source that this of the previous segment.</param> /// <param name="navigationProperty">The navigation property this node represents.</param> /// <param name="bindingPath">The binding path of navigation property</param> /// <exception cref="System.ArgumentNullException">Throws if the input navigationProperty.</exception> /// <exception cref="ArgumentException">Throws if the input navigationProperty targets more than one entity.</exception> internal SingleNavigationNode(IEdmNavigationSource navigationSource, IEdmNavigationProperty navigationProperty, IEdmPathExpression bindingPath) { ExceptionUtils.CheckArgumentNotNull(navigationProperty, "navigationProperty"); EdmMultiplicity multiplicity = navigationProperty.TargetMultiplicity(); if (multiplicity != EdmMultiplicity.One && multiplicity != EdmMultiplicity.ZeroOrOne) { throw new ArgumentException(ODataErrorStrings.Nodes_CollectionNavigationNode_MustHaveSingleMultiplicity); } this.navigationProperty = navigationProperty; this.entityTypeReference = (IEdmEntityTypeReference)this.NavigationProperty.Type; this.bindingPath = bindingPath; this.navigationSource = navigationSource != null?navigationSource.FindNavigationTarget(navigationProperty, bindingPath) : null; }
/// <summary> /// Translates V3 CollectionNavigationNode to V4 CollectionNavigationNode /// </summary> /// <param name="nodeIn">V3 CollectionNavigationNode</param> /// <returns>V4 CollectionNavigationNode</returns> public override QueryNode Visit(Data.OData.Query.SemanticAst.CollectionNavigationNode nodeIn) { IEdmPathExpression pathExpr = null; if (nodeIn.EntitySet != null) { IEdmNavigationSource navigationSource = v4model.FindDeclaredNavigationSource(nodeIn.EntitySet.Name); pathExpr = navigationSource.Path; } IEdmStructuredType v4Type = v4model.GetV4Definition(nodeIn.NavigationProperty.DeclaringType) as IEdmStructuredType; ExceptionUtil.IfNullThrowException(v4Type, "Unable to locate v4 structured type " + nodeIn.NavigationProperty.DeclaringType.GetFullTypeName()); IEdmNavigationProperty v4navProperty = v4Type.FindProperty(nodeIn.NavigationProperty.Name) as IEdmNavigationProperty; ExceptionUtil.IfNullThrowException(v4navProperty, "Unable to locate property " + nodeIn.NavigationProperty.Name); return new CollectionNavigationNode((SingleResourceNode)nodeIn.Source.Accept(this), v4navProperty, pathExpr); }
private static EdmOperationImport CreateFunctionImport( FunctionConfiguration function, EdmEntityContainer container, IEdmTypeReference returnReference, IEdmExpression expression, IEdmPathExpression pathExpression) { EdmFunction operation = new EdmFunction( function.Namespace, function.Name, returnReference, function.IsBindable, pathExpression, function.IsComposable); return(new EdmFunctionImport(container, function.Name, operation, expression, includeInServiceDocument: function.IncludeInServiceDocument)); }
/// <summary> /// Get the property path from the record using the given property name. /// </summary> /// <param name="record">The record expression.</param> /// <param name="propertyName">The property name.</param> /// <returns>The property path or null.</returns> public static string GetPropertyPath(this IEdmRecordExpression record, string propertyName) { Utils.CheckArgumentNull(record, nameof(record)); Utils.CheckArgumentNull(propertyName, nameof(propertyName)); if (record.Properties != null) { IEdmPropertyConstructor property = record.Properties.FirstOrDefault(e => e.Name == propertyName); if (property != null) { IEdmPathExpression value = property.Value as IEdmPathExpression; if (value != null) { return(value.Path); } } } return(null); }
/// <summary> /// Initializes a new <see cref="IEdmOperationImport"/> instance. /// </summary> /// <param name="name">name of the service operation.</param> /// <param name="function">Function imported in.</param> /// <param name="resultSet">EntitySet of the result expected from this operation.</param> public EdmFunctionImport AddFunctionAndFunctionImport(string name, IEdmTypeReference bindingType, IEdmTypeReference resultType, IEdmEntitySet resultSet, bool isBindable) { var edmFunction = new EdmFunction(this.Namespace, name, resultType, isBindable, null, false /*isComposable*/); if (isBindable) { edmFunction.AddParameter("bindingparameter", bindingType); } IEdmPathExpression entitySetExpression = null; if (resultSet != null) { entitySetExpression = new EdmPathExpression(resultSet.Name); } this.AddOperation(edmFunction); var functionImport = new EdmFunctionImport(this, name, edmFunction, entitySetExpression, false); this.AddOperationImport(name, functionImport); return(functionImport); }
internal void WriteFunctionImportElementHeader(IEdmFunctionImport functionImport) { this.xmlWriter.WriteStartElement("FunctionImport"); this.WriteRequiredAttribute <string>("Name", functionImport.Name, new Func <string, string>(EdmValueWriter.StringAsXml)); this.WriteOptionalAttribute <IEdmTypeReference>("ReturnType", functionImport.ReturnType, new Func <IEdmTypeReference, string>(this.TypeReferenceAsXml)); if (functionImport.IsComposable && functionImport.IsSideEffecting || !functionImport.IsComposable && !functionImport.IsSideEffecting) { this.WriteRequiredAttribute <bool>("IsSideEffecting", functionImport.IsSideEffecting, new Func <bool, string>(EdmValueWriter.BooleanAsXml)); } this.WriteOptionalAttribute <bool>("IsComposable", functionImport.IsComposable, false, new Func <bool, string>(EdmValueWriter.BooleanAsXml)); this.WriteOptionalAttribute <bool>("IsBindable", functionImport.IsBindable, false, new Func <bool, string>(EdmValueWriter.BooleanAsXml)); if (functionImport.EntitySet == null) { return; } else { IEdmEntitySetReferenceExpression entitySet = functionImport.EntitySet as IEdmEntitySetReferenceExpression; if (entitySet == null) { IEdmPathExpression edmPathExpression = functionImport.EntitySet as IEdmPathExpression; if (edmPathExpression == null) { throw new InvalidOperationException(Strings.EdmModel_Validator_Semantic_FunctionImportEntitySetExpressionIsInvalid(functionImport.Name)); } else { this.WriteOptionalAttribute <IEnumerable <string> >("EntitySetPath", edmPathExpression.Path, new Func <IEnumerable <string>, string>(EdmModelCsdlSchemaWriter.PathAsXml)); return; } } else { this.WriteOptionalAttribute <string>("EntitySet", entitySet.ReferencedEntitySet.Name, new Func <string, string>(EdmValueWriter.StringAsXml)); return; } } }
/// <summary> /// Maps an IEdmDelayedVAlue to an instance of an object. /// In the case that the delayedValue object represents a navigation path, /// performs additional work to map the navigation path to a delayedValue /// </summary> /// <param name="delayedValue">DelayedValue that is an element of the list</param> /// <returns>The object representation of the delayedValue</returns> private static object MapListElements(IEdmDelayedValue delayedValue) { IEdmValue edmValue; try { edmValue = delayedValue.Value; return(MapToClr(edmValue)); } catch (ArgumentNullException) { // This is a painful hack to deal with the fact that parsing the navigation // property returned a delayedValue that evaluates a NullException when you call .Value // Attempt to obtain the inner expression because we don't have access to the type of the Delayed Collection var innerExpression = delayedValue.GetPropertyByName <IEdmExpression>("Expression"); switch (innerExpression.ExpressionKind) { case EdmExpressionKind.NavigationPropertyPath: { IEdmPathExpression pe = innerExpression as IEdmPathExpression; if (pe == null) { throw new ArgumentNullException("delayedValue", "A IEdmExpression of delayedValue type NavigationPropertyPath was unable to be cast correctly to a IEdmNavigationPropertyPath"); } // Map navigation properties to strings for convenience return(string.Join("/", pe.Path)); } default: throw new NotImplementedException( string.Format("A custom mapping for ExpressionKind {0} has not yet been implemented.", innerExpression.ExpressionKind)); } } }
public static IEnumerable <IEdmStructuralProperty> GetConcurrencyProperties(this IEdmModel model, IEdmEntitySet entitySet) { Contract.Assert(model != null); Contract.Assert(entitySet != null); IList <IEdmStructuralProperty> results = new List <IEdmStructuralProperty>(); IEdmEntityType entityType = entitySet.EntityType(); var annotations = model.FindVocabularyAnnotations <IEdmValueAnnotation>(entitySet, CoreVocabularyModel.ConcurrencyTerm); IEdmValueAnnotation annotation = annotations.FirstOrDefault(); if (annotation != null) { IEdmCollectionExpression properties = annotation.Value as IEdmCollectionExpression; if (properties != null) { foreach (var property in properties.Elements) { IEdmPathExpression pathExpression = property as IEdmPathExpression; if (pathExpression != null) { // So far, we only consider the single path, because only the direct properties from declaring type are used. // However we have an issue tracking on: https://github.com/OData/WebApi/issues/472 string propertyName = pathExpression.Path.Single(); IEdmProperty edmProperty = entityType.FindProperty(propertyName); IEdmStructuralProperty structuralProperty = edmProperty as IEdmStructuralProperty; if (structuralProperty != null) { results.Add(structuralProperty); } } } } } return(results); }
/// <summary> /// Initializes a new instance of the <see cref="EdmFunction"/> class. /// </summary> /// <param name="namespaceName">Name of the namespace.</param> /// <param name="name">The name.</param> /// <param name="returnType">Type of the return.</param> /// <param name="isBound">if set to <c>true</c> [is bound].</param> /// <param name="entitySetPathExpression">The entity set path expression.</param> /// <param name="isComposable">A value indicating if the function is composable or not.</param> public EdmFunction(string namespaceName, string name, IEdmTypeReference returnType, bool isBound, IEdmPathExpression entitySetPathExpression, bool isComposable) : base(namespaceName, name, returnType, isBound, entitySetPathExpression) { EdmUtil.CheckArgumentNull(returnType, "returnType"); this.IsComposable = isComposable; }
/// <summary> /// Finds the entity set that a navigation property targets. /// </summary> /// <param name="navigationProperty">The navigation property.</param> /// <param name="bindingPath">The binding path of the navigation property</param> /// <returns>The entity set that the navigation property targets</returns> public override IEdmNavigationSource FindNavigationTarget(IEdmNavigationProperty navigationProperty, IEdmPathExpression bindingPath) { // 7.4.1 expected the path to be prefixed with the path to the contained navigation source. // For backward compatibility, if the binding path received starts with the path to this contained resource, // we trim it off and then treat the remainder as the path to the target. This logic should be removed in // the next breaking change as it could be ambiguous in the case that the prefix of the path to the contained // source matches a valid path to the target of the contained source. if (bindingPath != null) { if (bindingPath.Path.Length > this.FullNavigationPath.Length && bindingPath.Path.StartsWith(this.FullNavigationPath, System.StringComparison.Ordinal)) { bindingPath = new EdmPathExpression(bindingPath.Path.Substring(this.FullNavigationPath.Length + 1)); } } IEdmNavigationSource navigationTarget = base.FindNavigationTarget(navigationProperty, bindingPath); if (navigationTarget is IEdmUnknownEntitySet) { IEnumerable <string> segments = (bindingPath == null || string.IsNullOrEmpty(bindingPath.Path)) ? new string[] { navigationProperty.Name } : bindingPath.PathSegments; bindingPath = new EdmPathExpression(this.NavigationPath.PathSegments.Concat(segments)); return(this.parentNavigationSource.FindNavigationTarget(navigationProperty, bindingPath)); } return(navigationTarget); }
/// <summary> /// Initializes a new instance of the <see cref="EdmAction"/> class. /// </summary> /// <param name="namespaceName">Name of the namespace.</param> /// <param name="name">The name.</param> /// <param name="returnType">Type of the return.</param> /// <param name="isBound">if set to <c>true</c> [is bound].</param> /// <param name="entitySetPathExpression">The entity set path expression.</param> public EdmAction(string namespaceName, string name, IEdmTypeReference returnType, bool isBound, IEdmPathExpression entitySetPathExpression) : base(namespaceName, name, returnType, isBound, entitySetPathExpression) { }
/// <summary> /// Adds the action. /// </summary> /// <param name="name">The name.</param> /// <param name="boundType">Type of the bound.</param> /// <param name="resultType">Type of the result.</param> /// <param name="isBound">if set to <c>true</c> [is bound].</param> /// <param name="parameters">The parameters.</param> /// <returns></returns> public EdmAction AddAction(string name, IEdmTypeReference boundType, IEdmTypeReference resultType, bool isBound, IEdmPathExpression entitySetPathExpression, params Tuple<string, IEdmTypeReference>[] parameters) { var action = new EdmAction(namespaceName, name, resultType, isBound, entitySetPathExpression); if (isBound) { action.AddParameter(new EdmOperationParameter(action, "bindingparameter", boundType)); } this.AddOperation(action); return action; }
private static EdmOperationImport CreateFunctionImport( FunctionConfiguration function, EdmEntityContainer container, IEdmTypeReference returnReference, IEdmExpression expression, IEdmPathExpression pathExpression) { EdmFunction operation = new EdmFunction( container.Namespace, function.Name, returnReference, function.IsBindable, pathExpression, function.IsComposable); return new EdmFunctionImport(container, function.Name, operation, expression, includeInServiceDocument: function.IncludeInServiceDocument); }
private static EdmOperationImport CreateActionImport( ProcedureConfiguration procedure, EdmEntityContainer container, IEdmTypeReference returnReference, IEdmExpression expression, IEdmPathExpression pathExpression) { EdmAction operation = new EdmAction( container.Namespace, procedure.Name, returnReference, procedure.IsBindable, pathExpression); return new EdmActionImport(container, procedure.Name, operation, expression); }
/// <summary> /// Adds the function. /// </summary> /// <param name="name">The name.</param> /// <param name="boundType">Type of the bound.</param> /// <param name="resultType">Type of the result.</param> /// <param name="isBound">if set to <c>true</c> [is bound].</param> /// <param name="parameters">The parameters.</param> /// <returns></returns> public EdmFunction AddFunction(string name, IEdmTypeReference boundType, IEdmTypeReference returnType, bool isBound, IEdmPathExpression entitySetPathExpression, bool isComposable) { var function = new EdmFunction(namespaceName, name, returnType, isBound, entitySetPathExpression, isComposable); if (isBound) { function.AddParameter("bindingparameter", boundType); } this.AddOperation(function); return function; }