protected virtual CsdlTypeReference ParseTypeReference(string typeString, XmlElementValueCollection childValues, CsdlLocation parentLocation, Optionality typeInfoOptionality) { bool isNullable = OptionalBoolean(CsdlConstants.Attribute_Nullable) ?? CsdlConstants.Default_Nullable; CsdlTypeReference elementType = null; if (typeString != null) { string[] typeInformation = typeString.Split(new char[] { '(', ')' }); string typeName = typeInformation[0]; switch (typeName) { case CsdlConstants.Value_Collection: { string elementTypeName = typeInformation.Length > 1 ? typeInformation[1] : typeString; elementType = new CsdlExpressionTypeReference( new CsdlCollectionType( this.ParseNamedTypeReference(elementTypeName, isNullable, parentLocation), parentLocation), isNullable, parentLocation); } break; case CsdlConstants.Value_Ref: { string elementTypeName = typeInformation.Length > 1 ? typeInformation[1] : typeString; elementType = new CsdlExpressionTypeReference( new CsdlEntityReferenceType( this.ParseNamedTypeReference(elementTypeName, isNullable, parentLocation), parentLocation), CsdlConstants.Default_Nullable, parentLocation); } break; default: elementType = this.ParseNamedTypeReference(typeName, isNullable, parentLocation); break; } } else if (childValues != null) { elementType = childValues.ValuesOfType <CsdlTypeReference>().FirstOrDefault(); } if (elementType == null && typeInfoOptionality == Optionality.Required) { if (childValues != null) { // If childValues is null, then it is the case when a required type attribute was expected. // In this case, we do not report the error as it should already be reported by EdmXmlDocumentParser.RequiredType method. this.ReportError(parentLocation, EdmErrorCode.MissingType, Edm.Strings.CsdlParser_MissingTypeAttributeOrElement); } else { Debug.Assert(this.Errors.Any(), "There should be an error reported for the missing required type attribute."); } elementType = new CsdlNamedTypeReference(String.Empty, isNullable, parentLocation); } return(elementType); }
public static CsdlTypeReference ParseCsdlTypeReference(JsonElement element, JsonParserContext context) { Debug.Assert(element.ValueKind == JsonValueKind.Object); // $Type // For single-valued terms the value of $Type is the qualified name of the property/term�s type. // For collection-valued terms the value of $Type is the qualified name of the term�s item type, and the member $Collection MUST be present with the literal value true. // Absence of the $Type member means the type is Edm.String. string typeName = element.ParseOptionalProperty("$Type", context, (v, p) => v.ParseAsString(p)); typeName = typeName == null ? "Edm.String" : typeName; // $Collection // For collection-valued properties the value of $Type is the qualified name of the property�s item type, // and the member $Collection MUST be present with the literal value true. bool?collection = element.ParseOptionalProperty("$Collection", context, (v, p) => v.ParseAsBoolean(p)); // $Nullable, // The value of $Nullable is one of the Boolean literals true or false. Absence of the member means false. bool?isNullable = element.ParseOptionalProperty("$Nullable", context, (v, p) => v.ParseAsBoolean(p)); bool nullable = isNullable == null ? false : isNullable.Value; // $MaxLength, // The value of $MaxLength is a positive integer. // CSDL xml defines a symbolic value max that is only allowed in OData 4.0 responses. This symbolic value is not allowed in CDSL JSON documents at all. int?maxLength = element.ParseOptionalProperty("$MaxLength", context, (v, p) => v.ParseAsInteger(p)); // $Unicode, // The value of $Unicode is one of the Boolean literals true or false. Absence of the member means true. bool?unicode = element.ParseOptionalProperty("$Unicode", context, (v, p) => v.ParseAsBoolean(p)); // $Precision, // The value of $Precision is a number. int?precision = element.ParseOptionalProperty("$Precision", context, (v, p) => v.ParseAsInteger(p)); // $Scale, int?scale = element.ParseOptionalProperty("$Scale", context, (v, p) => v.ParseAsInteger(p)); // $SRID, // The value of $SRID is a string containing a number or the symbolic value variable. // So far, ODL doesn't support string of SRID. int?srid = element.ParseOptionalProperty("$SRID", context, (v, p) => v.ParseAsInteger(p)); CsdlLocation location = context.Location(); CsdlTypeReference csdlType = ParseNamedTypeReference(typeName, nullable, false, maxLength, unicode, precision, scale, srid, location); if (collection != null && collection.Value) { csdlType = new CsdlExpressionTypeReference(new CsdlCollectionType(csdlType, location), nullable, location); } return(csdlType); }
public void ParseIsOfExpressionWorksAsExpected() { string json = @" { ""$IsOf"": { ""$Path"": ""FirstName"" }, ""$Type"": ""self.PreferredCustomer"", ""$Collection"": true }"; CsdlExpressionBase expressionBase = ParseExpression(json); Assert.NotNull(expressionBase); CsdlIsTypeExpression isTypeExp = Assert.IsType <CsdlIsTypeExpression>(expressionBase); Assert.NotNull(isTypeExp.Type); CsdlExpressionTypeReference expTypeReference = Assert.IsType <CsdlExpressionTypeReference>(isTypeExp.Type); CsdlCollectionType collectionType = Assert.IsType <CsdlCollectionType>(expTypeReference.TypeExpression); CsdlNamedTypeReference namedType = Assert.IsType <CsdlNamedTypeReference>(collectionType.ElementType); Assert.Equal("self.PreferredCustomer", namedType.FullName); Assert.NotNull(isTypeExp.Operand); Assert.IsType <CsdlPathExpression>(isTypeExp.Operand); }
public CsdlSemanticsEntityReferenceTypeExpression(CsdlExpressionTypeReference expressionUsage, CsdlSemanticsTypeDefinition type) : base(expressionUsage, type) { }
protected CsdlSemanticsTypeExpression(CsdlExpressionTypeReference expressionUsage, CsdlSemanticsTypeDefinition type) : base(expressionUsage) { this.expressionUsage = expressionUsage; this.type = type; }
public void ParseCsdlComplexTypeWithMembersWorksAsExpected() { string json = @"""CountRestrictionsType"": { ""$Kind"": ""ComplexType"", ""Countable"": { ""$Type"": ""Edm.Boolean"", ""$DefaultValue"": true, ""@Core.Description"": ""Entities can be counted (only valid if targeting an entity set)"" }, ""NonCountableProperties"": { ""$Collection"": true, ""$Type"": ""Edm.PropertyPath"", ""@Core.Description"": ""Members of these collection properties cannot be counted"" }, ""NonCountableNavigationProperties"": { ""$Collection"": true, ""$Type"": ""Edm.NavigationPropertyPath"", ""@Core.Description"": ""Members of these navigation properties cannot be counted"" } }"; CsdlComplexType complexType = ParseCsdlSchemaElement(json, SchemaJsonParser.ParseCsdlComplexType); Assert.NotNull(complexType); Assert.Equal("CountRestrictionsType", complexType.Name); Assert.False(complexType.IsAbstract); Assert.False(complexType.IsOpen); Assert.Null(complexType.BaseTypeName); Assert.Empty(complexType.NavigationProperties); Assert.Equal(3, complexType.StructuralProperties.Count()); // Countable CsdlProperty countable = complexType.StructuralProperties.FirstOrDefault(p => p.Name == "Countable"); Assert.NotNull(countable); CsdlPrimitiveTypeReference primitiveType = Assert.IsType <CsdlPrimitiveTypeReference>(countable.Type); Assert.Equal(EdmPrimitiveTypeKind.Boolean, primitiveType.Kind); Assert.Equal("true", countable.DefaultValue); Assert.IsType <CsdlConstantExpression>(Assert.Single(countable.VocabularyAnnotations).Expression); // NonCountableProperties CsdlProperty nonCountable = complexType.StructuralProperties.FirstOrDefault(p => p.Name == "NonCountableProperties"); Assert.NotNull(nonCountable); CsdlExpressionTypeReference expressionType = Assert.IsType <CsdlExpressionTypeReference>(nonCountable.Type); CsdlNamedTypeReference namedType = Assert.IsType <CsdlNamedTypeReference>(Assert.IsType <CsdlCollectionType>(expressionType.TypeExpression).ElementType); Assert.Equal("Edm.PropertyPath", namedType.FullName); Assert.Null(nonCountable.DefaultValue); Assert.IsType <CsdlConstantExpression>(Assert.Single(nonCountable.VocabularyAnnotations).Expression); // NonCountableNavigationProperties CsdlProperty nonCountableNav = complexType.StructuralProperties.FirstOrDefault(p => p.Name == "NonCountableNavigationProperties"); Assert.NotNull(nonCountableNav); expressionType = Assert.IsType <CsdlExpressionTypeReference>(nonCountableNav.Type); namedType = Assert.IsType <CsdlNamedTypeReference>(Assert.IsType <CsdlCollectionType>(expressionType.TypeExpression).ElementType); Assert.Equal("Edm.NavigationPropertyPath", namedType.FullName); Assert.Null(nonCountableNav.DefaultValue); Assert.IsType <CsdlConstantExpression>(Assert.Single(nonCountableNav.VocabularyAnnotations).Expression); }
public void ParseCsdlOperationForFunctionWithMembersWorksAsExpected() { string json = @"""CreatedEntities"": [ { ""$Kind"": ""Function"", ""$Parameter"": [ { ""$Name"": ""before"", ""$Type"": ""Edm.DateTimeOffset"", ""$Nullable"": true, ""$Precision"": 10 }, { ""$Name"": ""after"", ""$Type"": ""Edm.DateTimeOffset"", ""$Precision"": 9 } ], ""$ReturnType"": { ""$Collection"": true, ""$Type"": ""Edm.EntityType"", ""$Nullable"": true }, ""$IsComposable"": true } ]"; IList <CsdlOperation> operations = ParseCsdlSchemaElement(json, SchemaJsonParser.TryParseCsdlOperationOverload); Assert.NotNull(operations); CsdlOperation operation = Assert.Single(operations); CsdlFunction function = Assert.IsType <CsdlFunction>(operation); Assert.Equal("CreatedEntities", function.Name); Assert.False(function.IsBound); Assert.True(function.IsComposable); Assert.Null(function.EntitySetPath); // Parameter Assert.Equal(2, function.Parameters.Count()); CsdlOperationParameter parameter = function.Parameters.First(c => c.Name == "before"); Assert.False(parameter.IsOptional); Assert.Null(parameter.DefaultValue); CsdlTemporalTypeReference temporalType = Assert.IsType <CsdlTemporalTypeReference>(parameter.Type); Assert.Equal(EdmPrimitiveTypeKind.DateTimeOffset, temporalType.Kind); Assert.True(temporalType.IsNullable); Assert.Equal(10, temporalType.Precision.Value); parameter = function.Parameters.First(c => c.Name == "after"); Assert.False(parameter.IsOptional); Assert.Null(parameter.DefaultValue); temporalType = Assert.IsType <CsdlTemporalTypeReference>(parameter.Type); Assert.Equal(EdmPrimitiveTypeKind.DateTimeOffset, temporalType.Kind); Assert.False(temporalType.IsNullable); Assert.Equal(9, temporalType.Precision.Value); // ReturnType Assert.NotNull(function.Return); CsdlExpressionTypeReference expTypeRef = Assert.IsType <CsdlExpressionTypeReference>(operation.Return.ReturnType); Assert.True(expTypeRef.IsNullable); CsdlNamedTypeReference namedType = Assert.IsType <CsdlNamedTypeReference>(Assert.IsType <CsdlCollectionType>(expTypeRef.TypeExpression).ElementType); Assert.True(namedType.IsNullable); // derived from collection Assert.Equal("Edm.EntityType", namedType.FullName); }
internal static IEdmTypeReference WrapTypeReference(CsdlSemanticsSchema schema, CsdlTypeReference type) { CsdlNamedTypeReference reference = type as CsdlNamedTypeReference; if (reference != null) { CsdlPrimitiveTypeReference reference2 = reference as CsdlPrimitiveTypeReference; if (reference2 != null) { switch (reference2.Kind) { case EdmPrimitiveTypeKind.Binary: return(new CsdlSemanticsBinaryTypeReference(schema, (CsdlBinaryTypeReference)reference2)); case EdmPrimitiveTypeKind.Boolean: case EdmPrimitiveTypeKind.Byte: case EdmPrimitiveTypeKind.Double: case EdmPrimitiveTypeKind.Guid: case EdmPrimitiveTypeKind.Int16: case EdmPrimitiveTypeKind.Int32: case EdmPrimitiveTypeKind.Int64: case EdmPrimitiveTypeKind.SByte: case EdmPrimitiveTypeKind.Single: case EdmPrimitiveTypeKind.Stream: return(new CsdlSemanticsPrimitiveTypeReference(schema, reference2)); case EdmPrimitiveTypeKind.DateTime: case EdmPrimitiveTypeKind.DateTimeOffset: case EdmPrimitiveTypeKind.Time: return(new CsdlSemanticsTemporalTypeReference(schema, (CsdlTemporalTypeReference)reference2)); case EdmPrimitiveTypeKind.Decimal: return(new CsdlSemanticsDecimalTypeReference(schema, (CsdlDecimalTypeReference)reference2)); case EdmPrimitiveTypeKind.String: return(new CsdlSemanticsStringTypeReference(schema, (CsdlStringTypeReference)reference2)); case EdmPrimitiveTypeKind.Geography: case EdmPrimitiveTypeKind.GeographyPoint: case EdmPrimitiveTypeKind.GeographyLineString: case EdmPrimitiveTypeKind.GeographyPolygon: case EdmPrimitiveTypeKind.GeographyCollection: case EdmPrimitiveTypeKind.GeographyMultiPolygon: case EdmPrimitiveTypeKind.GeographyMultiLineString: case EdmPrimitiveTypeKind.GeographyMultiPoint: case EdmPrimitiveTypeKind.Geometry: case EdmPrimitiveTypeKind.GeometryPoint: case EdmPrimitiveTypeKind.GeometryLineString: case EdmPrimitiveTypeKind.GeometryPolygon: case EdmPrimitiveTypeKind.GeometryCollection: case EdmPrimitiveTypeKind.GeometryMultiPolygon: case EdmPrimitiveTypeKind.GeometryMultiLineString: case EdmPrimitiveTypeKind.GeometryMultiPoint: return(new CsdlSemanticsSpatialTypeReference(schema, (CsdlSpatialTypeReference)reference2)); } } return(new CsdlSemanticsNamedTypeReference(schema, reference)); } CsdlExpressionTypeReference expressionUsage = type as CsdlExpressionTypeReference; if (expressionUsage != null) { CsdlRowType typeExpression = expressionUsage.TypeExpression as CsdlRowType; if (typeExpression != null) { return(new CsdlSemanticsRowTypeExpression(expressionUsage, new CsdlSemanticsRowTypeDefinition(schema, typeExpression))); } CsdlCollectionType collection = expressionUsage.TypeExpression as CsdlCollectionType; if (collection != null) { return(new CsdlSemanticsCollectionTypeExpression(expressionUsage, new CsdlSemanticsCollectionTypeDefinition(schema, collection))); } CsdlEntityReferenceType entityTypeReference = expressionUsage.TypeExpression as CsdlEntityReferenceType; if (entityTypeReference != null) { return(new CsdlSemanticsEntityReferenceTypeExpression(expressionUsage, new CsdlSemanticsEntityReferenceTypeDefinition(schema, entityTypeReference))); } } return(null); }