Example #1
0
        internal static bool TryWriteCsdl(IEdmModel model, Func<string, XmlWriter> writerProvider, bool singleFileExpected, out IEnumerable<EdmError> errors)
        {
            EdmUtil.CheckArgumentNull(model, "model");
            EdmUtil.CheckArgumentNull(writerProvider, "writerProvider");

            errors = model.GetSerializationErrors();
            if (errors.FirstOrDefault() != null)
            {
                return false;
            }

            IEnumerable<EdmSchema> schemas = new EdmModelSchemaSeparationSerializationVisitor(model).GetSchemas();
            if (schemas.Count() > 1 && singleFileExpected)
            {
                errors = new EdmError[] { new EdmError(new CsdlLocation(0, 0), EdmErrorCode.SingleFileExpected, Edm.Strings.Serializer_SingleFileExpected) };
                return false;
            }

            if (schemas.Count() == 0)
            {
                errors = new EdmError[] { new EdmError(new CsdlLocation(0, 0), EdmErrorCode.NoSchemasProduced, Edm.Strings.Serializer_NoSchemasProduced) };
                return false;
            }

            WriteSchemas(model, schemas, writerProvider);

            errors = Enumerable.Empty<EdmError>();
            return true;
        }
Example #2
0
        /// <summary>
        /// Outputs an EDMX artifact to the provided XmlWriter.
        /// </summary>
        /// <param name="model">Model to be written.</param>
        /// <param name="writer">XmlWriter the generated EDMX will be written to.</param>
        /// <param name="target">Target implementation of the EDMX being generated.</param>
        /// <param name="errors">Errors that prevented successful serialization, or no errors if serialization was successfull. </param>
        /// <returns>A value indicating whether serialization was successful.</returns>
        public static bool TryWriteEdmx(IEdmModel model, XmlWriter writer, EdmxTarget target, out IEnumerable<EdmError> errors)
        {
            EdmUtil.CheckArgumentNull(model, "model");
            EdmUtil.CheckArgumentNull(writer, "writer");

            errors = model.GetSerializationErrors();
            if (errors.FirstOrDefault() != null)
            {
                return false;
            }

            Version edmxVersion = model.GetEdmxVersion();

            if (edmxVersion != null)
            {
                if (!CsdlConstants.SupportedEdmxVersions.ContainsKey(edmxVersion))
                {
                    errors = new EdmError[] { new EdmError(new CsdlLocation(0, 0), EdmErrorCode.UnknownEdmxVersion, Edm.Strings.Serializer_UnknownEdmxVersion) };
                    return false;
                }
            }
            else if (!CsdlConstants.EdmToEdmxVersions.TryGetValue(model.GetEdmVersion() ?? EdmConstants.EdmVersionLatest, out edmxVersion))
            {
                errors = new EdmError[] { new EdmError(new CsdlLocation(0, 0), EdmErrorCode.UnknownEdmVersion, Edm.Strings.Serializer_UnknownEdmVersion) };
                return false;
            }

            IEnumerable<EdmSchema> schemas = new EdmModelSchemaSeparationSerializationVisitor(model).GetSchemas();

            EdmxWriter edmxWriter = new EdmxWriter(model, schemas, writer, edmxVersion, target);
            edmxWriter.WriteEdmx();

            errors = Enumerable.Empty<EdmError>();
            return true;
        }
        public static bool IsMatch(ExpectedEdmError expectedError, EdmError actualError)
        {
            if (expectedError.ErrorCode != actualError.ErrorCode)
            {
                return false;
            }

            return stringResourceVerifier.IsMatch(expectedError.MessageResourceKey, actualError.ErrorMessage, false, expectedError.MessageArguments.ToArray());
        }
Example #4
0
        public static bool TryParse(IEnumerable<XmlReader> csdlReaders, out CsdlModel entityModel, out IEnumerable<EdmError> errors)
        {
            EdmUtil.CheckArgumentNull(csdlReaders, "csdlReaders");
            CsdlParser parser = new CsdlParser();
            int readerCount = 0;
            foreach (var inputReader in csdlReaders)
            {
                if (inputReader != null)
                {
                    try
                    {
                        parser.AddReader(inputReader);
                    }
                    catch (XmlException e)
                    {
                        entityModel = null;
                        errors = new EdmError[] { new EdmError(new CsdlLocation(e.LineNumber, e.LinePosition), EdmErrorCode.XmlError, e.Message) };

                        return false;
                    }
                }
                else
                {
                    entityModel = null;
                    errors = new EdmError[] { new EdmError(null, EdmErrorCode.NullXmlReader, Edm.Strings.CsdlParser_NullXmlReader) };

                    return false;
                }

                readerCount++;
            }

            if (readerCount == 0)
            {
                entityModel = null;
                errors = new EdmError[] { new EdmError(null, EdmErrorCode.NoReadersProvided, Edm.Strings.CsdlParser_NoReadersProvided) };

                return false;
            }

            bool success = parser.GetResult(out entityModel, out errors);
            if (!success)
            {
                entityModel = null;
            }

            return success;
        }
        private static bool TryCastBinaryConstantAsType(IEdmBinaryConstantExpression expression, IEdmTypeReference type, out IEnumerable <EdmError> discoveredErrors)
        {
            if (!type.IsBinary())
            {
                discoveredErrors = new EdmError[] { new EdmError(expression.Location(), EdmErrorCode.ExpressionPrimitiveKindNotValidForAssertedType, Edm.Strings.EdmModel_Validator_Semantic_ExpressionPrimitiveKindNotValidForAssertedType) };
                return(false);
            }

            IEdmBinaryTypeReference binaryType = type.AsBinary();

            if (binaryType.MaxLength.HasValue && expression.Value.Length > binaryType.MaxLength.Value)
            {
                discoveredErrors = new EdmError[] { new EdmError(expression.Location(), EdmErrorCode.BinaryConstantLengthOutOfRange, Edm.Strings.EdmModel_Validator_Semantic_BinaryConstantLengthOutOfRange(expression.Value.Length, binaryType.MaxLength.Value)) };
                return(false);
            }

            discoveredErrors = Enumerable.Empty <EdmError>();
            return(true);
        }
Example #6
0
        private static bool TestTypeMatch(this IEdmType expressionType, IEdmType assertedType, EdmLocation location, bool matchExactly, out IEnumerable <EdmError> discoveredErrors)
        {
            if (matchExactly)
            {
                if (!expressionType.IsEquivalentTo(assertedType))
                {
                    discoveredErrors = new EdmError[] { new EdmError(location, EdmErrorCode.ExpressionNotValidForTheAssertedType, Edm.Strings.EdmModel_Validator_Semantic_ExpressionNotValidForTheAssertedType) };
                    return(false);
                }
            }
            else
            {
                // A bad type matches anything (so as to avoid generating spurious errors).
                if (expressionType.TypeKind == EdmTypeKind.None || expressionType.IsBad())
                {
                    discoveredErrors = Enumerable.Empty <EdmError>();
                    return(true);
                }

                if (expressionType.TypeKind == EdmTypeKind.Primitive && assertedType.TypeKind == EdmTypeKind.Primitive)
                {
                    IEdmPrimitiveType primitiveExpressionType = expressionType as IEdmPrimitiveType;
                    IEdmPrimitiveType primitiveAssertedType   = assertedType as IEdmPrimitiveType;
                    if (!primitiveExpressionType.PrimitiveKind.PromotesTo(primitiveAssertedType.PrimitiveKind))
                    {
                        discoveredErrors = new EdmError[] { new EdmError(location, EdmErrorCode.ExpressionPrimitiveKindNotValidForAssertedType, Edm.Strings.EdmModel_Validator_Semantic_ExpressionPrimitiveKindCannotPromoteToAssertedType(expressionType.ToTraceString(), assertedType.ToTraceString())) };
                        return(false);
                    }
                }
                else
                {
                    if (!expressionType.IsOrInheritsFrom(assertedType))
                    {
                        discoveredErrors = new EdmError[] { new EdmError(location, EdmErrorCode.ExpressionNotValidForTheAssertedType, Edm.Strings.EdmModel_Validator_Semantic_ExpressionNotValidForTheAssertedType) };
                        return(false);
                    }
                }
            }

            discoveredErrors = Enumerable.Empty <EdmError>();
            return(true);
        }
        internal static bool TryCastPrimitiveAsType(this IEdmPrimitiveValue expression, IEdmTypeReference type, out IEnumerable <EdmError> discoveredErrors)
        {
            if (!type.IsPrimitive())
            {
                discoveredErrors = new EdmError[] { new EdmError(expression.Location(), EdmErrorCode.PrimitiveConstantExpressionNotValidForNonPrimitiveType, Edm.Strings.EdmModel_Validator_Semantic_PrimitiveConstantExpressionNotValidForNonPrimitiveType) };
                return(false);
            }

            switch (expression.ValueKind)
            {
            case EdmValueKind.Binary:
                return(TryCastBinaryConstantAsType((IEdmBinaryConstantExpression)expression, type, out discoveredErrors));

            case EdmValueKind.Boolean:
                return(TryCastBooleanConstantAsType((IEdmBooleanConstantExpression)expression, type, out discoveredErrors));

            case EdmValueKind.DateTimeOffset:
                return(TryCastDateTimeOffsetConstantAsType((IEdmDateTimeOffsetConstantExpression)expression, type, out discoveredErrors));

            case EdmValueKind.Decimal:
                return(TryCastDecimalConstantAsType((IEdmDecimalConstantExpression)expression, type, out discoveredErrors));

            case EdmValueKind.Floating:
                return(TryCastFloatingConstantAsType((IEdmFloatingConstantExpression)expression, type, out discoveredErrors));

            case EdmValueKind.Guid:
                return(TryCastGuidConstantAsType((IEdmGuidConstantExpression)expression, type, out discoveredErrors));

            case EdmValueKind.Integer:
                return(TryCastIntegerConstantAsType((IEdmIntegerConstantExpression)expression, type, out discoveredErrors));

            case EdmValueKind.String:
                return(TryCastStringConstantAsType((IEdmStringConstantExpression)expression, type, out discoveredErrors));

            case EdmValueKind.Duration:
                return(TryCastDurationConstantAsType((IEdmDurationConstantExpression)expression, type, out discoveredErrors));

            default:
                discoveredErrors = new EdmError[] { new EdmError(expression.Location(), EdmErrorCode.ExpressionPrimitiveKindNotValidForAssertedType, Edm.Strings.EdmModel_Validator_Semantic_ExpressionPrimitiveKindNotValidForAssertedType) };
                return(false);
            }
        }
Example #8
0
        internal static bool TryCastCollectionAsType(this IEdmCollectionExpression expression, IEdmTypeReference type, IEdmType context, bool matchExactly, out IEnumerable <EdmError> discoveredErrors)
        {
            if (!type.IsCollection())
            {
                discoveredErrors = new EdmError[] { new EdmError(expression.Location(), EdmErrorCode.CollectionExpressionNotValidForNonCollectionType, Edm.Strings.EdmModel_Validator_Semantic_CollectionExpressionNotValidForNonCollectionType) };
                return(false);
            }

            IEdmTypeReference collectionElementType = type.AsCollection().ElementType();
            bool                   success          = true;
            List <EdmError>        errors           = new List <EdmError>();
            IEnumerable <EdmError> recursiveErrors;

            foreach (IEdmExpression element in expression.Elements)
            {
                success = TryCast(element, collectionElementType, context, matchExactly, out recursiveErrors) && success;
                errors.AddRange(recursiveErrors);
            }

            discoveredErrors = errors;
            return(success);
        }
Example #9
0
        private static bool TryCastEnumConstantAsType(IEdmEnumMemberExpression expression, IEdmTypeReference type, bool matchExactly, out IEnumerable <EdmError> discoveredErrors)
        {
            if (!type.IsEnum())
            {
                discoveredErrors = new EdmError[] {
                    new EdmError(expression.Location(),
                                 EdmErrorCode.ExpressionEnumKindNotValidForAssertedType,
                                 Edm.Strings.EdmModel_Validator_Semantic_ExpressionEnumKindNotValidForAssertedType)
                };
                return(false);
            }

            foreach (var member in expression.EnumMembers)
            {
                if (!TestTypeMatch(member.DeclaringType, type.Definition, expression.Location(), matchExactly, out discoveredErrors))
                {
                    return(false);
                }
            }

            discoveredErrors = Enumerable.Empty <EdmError>();
            return(true);
        }
        private static bool TryCastIntegerConstantAsType(IEdmIntegerConstantExpression expression, IEdmTypeReference type, out IEnumerable<EdmError> discoveredErrors)
        {
            if (!type.IsIntegral())
            {
                discoveredErrors = new EdmError[] { new EdmError(expression.Location(), EdmErrorCode.ExpressionPrimitiveKindNotValidForAssertedType, Edm.Strings.EdmModel_Validator_Semantic_ExpressionPrimitiveKindNotValidForAssertedType) };
                return false;
            }

            switch (type.PrimitiveKind())
            {
                case EdmPrimitiveTypeKind.Int64:
                    return TryCastIntegerConstantInRange(expression, Int64.MinValue, Int64.MaxValue, out discoveredErrors);
                case EdmPrimitiveTypeKind.Int32:
                    return TryCastIntegerConstantInRange(expression, Int32.MinValue, Int32.MaxValue, out discoveredErrors);
                case EdmPrimitiveTypeKind.Int16:
                    return TryCastIntegerConstantInRange(expression, Int16.MinValue, Int16.MaxValue, out discoveredErrors);
                case EdmPrimitiveTypeKind.Byte:
                    return TryCastIntegerConstantInRange(expression, Byte.MinValue, Byte.MaxValue, out discoveredErrors);
                case EdmPrimitiveTypeKind.SByte:
                    return TryCastIntegerConstantInRange(expression, SByte.MinValue, SByte.MaxValue, out discoveredErrors);
                default:
                    discoveredErrors = new EdmError[] { new EdmError(expression.Location(), EdmErrorCode.ExpressionPrimitiveKindNotValidForAssertedType, Edm.Strings.EdmModel_Validator_Semantic_ExpressionPrimitiveKindNotValidForAssertedType) };
                    return false;
            }
        }
        private static bool TryCastBooleanConstantAsType(IEdmBooleanConstantExpression expression, IEdmTypeReference type, out IEnumerable<EdmError> discoveredErrors)
        {
            if (!type.IsBoolean())
            {
                discoveredErrors = new EdmError[] { new EdmError(expression.Location(), EdmErrorCode.ExpressionPrimitiveKindNotValidForAssertedType, Edm.Strings.EdmModel_Validator_Semantic_ExpressionPrimitiveKindNotValidForAssertedType) };
                return false;
            }

            discoveredErrors = Enumerable.Empty<EdmError>();
            return true;
        }
        internal static bool TryCastCollectionAsType(this IEdmCollectionExpression expression, IEdmTypeReference type, IEdmType context, bool matchExactly, out IEnumerable<EdmError> discoveredErrors)
        {
            if (!type.IsCollection())
            {
                discoveredErrors = new EdmError[] { new EdmError(expression.Location(), EdmErrorCode.CollectionExpressionNotValidForNonCollectionType, Edm.Strings.EdmModel_Validator_Semantic_CollectionExpressionNotValidForNonCollectionType) };
                return false;
            }

            IEdmTypeReference collectionElementType = type.AsCollection().ElementType();
            bool success = true;
            List<EdmError> errors = new List<EdmError>();
            IEnumerable<EdmError> recursiveErrors;
            foreach (IEdmExpression element in expression.Elements)
            {
                success = TryCast(element, collectionElementType, context, matchExactly, out recursiveErrors) && success;
                errors.AddRange(recursiveErrors);
            }

            discoveredErrors = errors;
            return success;
        }
        internal static bool TryCastRecordAsType(this IEdmRecordExpression expression, IEdmTypeReference type, IEdmType context, bool matchExactly, out IEnumerable<EdmError> discoveredErrors)
        {
            EdmUtil.CheckArgumentNull(expression, "expression");
            EdmUtil.CheckArgumentNull(type, "type");

            if (!type.IsStructured())
            {
                discoveredErrors = new EdmError[] { new EdmError(expression.Location(), EdmErrorCode.RecordExpressionNotValidForNonStructuredType, Edm.Strings.EdmModel_Validator_Semantic_RecordExpressionNotValidForNonStructuredType) };
                return false;
            }

            HashSetInternal<string> foundProperties = new HashSetInternal<string>();
            List<EdmError> errors = new List<EdmError>();

            IEdmStructuredTypeReference structuredType = type.AsStructured();
            foreach (IEdmProperty typeProperty in structuredType.StructuredDefinition().Properties())
            {
                IEdmPropertyConstructor expressionProperty = expression.Properties.FirstOrDefault(p => p.Name == typeProperty.Name);
                if (expressionProperty == null)
                {
                    errors.Add(new EdmError(expression.Location(), EdmErrorCode.RecordExpressionMissingRequiredProperty, Edm.Strings.EdmModel_Validator_Semantic_RecordExpressionMissingProperty(typeProperty.Name)));
                }
                else
                {
                    IEnumerable<EdmError> recursiveErrors;
                    if (!expressionProperty.Value.TryCast(typeProperty.Type, context, matchExactly, out recursiveErrors))
                    {
                        foreach (EdmError error in recursiveErrors)
                        {
                            errors.Add(error);
                        }
                    }

                    foundProperties.Add(typeProperty.Name);
                }
            }

            if (!structuredType.IsOpen())
            {
                foreach (IEdmPropertyConstructor property in expression.Properties)
                {
                    if (!foundProperties.Contains(property.Name))
                    {
                        errors.Add(new EdmError(expression.Location(), EdmErrorCode.RecordExpressionHasExtraProperties, Edm.Strings.EdmModel_Validator_Semantic_RecordExpressionHasExtraProperties(property.Name)));
                    }
                }
            }

            if (errors.FirstOrDefault() != null)
            {
                discoveredErrors = errors;
                return false;
            }

            discoveredErrors = Enumerable.Empty<EdmError>();
            return true;
        }
 /// <summary>
 /// Register an error with the validation context.
 /// </summary>
 /// <param name="error">Error to register.</param>
 public void AddError(EdmError error)
 {
     this.errors.Add(error);
 }
        private static bool TestNullabilityMatch(this IEdmTypeReference expressionType, IEdmTypeReference assertedType, EdmLocation location, out IEnumerable<EdmError> discoveredErrors)
        {
            if (!assertedType.IsNullable && expressionType.IsNullable)
            {
                discoveredErrors = new EdmError[] { new EdmError(location, EdmErrorCode.CannotAssertNullableTypeAsNonNullableType, Edm.Strings.EdmModel_Validator_Semantic_CannotAssertNullableTypeAsNonNullableType(expressionType.FullName())) };
                return false;
            }

            discoveredErrors = Enumerable.Empty<EdmError>();
            return true;
        }
        /// <summary>
        /// Determines if the type of an expression is compatible with the provided type
        /// </summary>
        /// <param name="expression">The expression to assert the type of.</param>
        /// <param name="type">The type to assert the expression as.</param>
        /// <param name="context">The context paths are to be evaluated in.</param>
        /// <param name="matchExactly">A value indicating whether the expression must match the asserted type exactly, or simply be compatible.</param>
        /// <param name="discoveredErrors">Errors produced if the expression does not match the specified type.</param>
        /// <returns>A value indicating whether the expression is valid for the given type or not.</returns>
        /// <remarks>If the expression has an associated type, this function will check that it matches the expected type and stop looking further. 
        /// If an expression claims a type, it must be validated that the type is valid for the expression. If the expression does not claim a type
        /// this method will attempt to check the validity of the expression itself with the asserted type.</remarks>
        public static bool TryCast(this IEdmExpression expression, IEdmTypeReference type, IEdmType context, bool matchExactly, out IEnumerable<EdmError> discoveredErrors)
        {
            EdmUtil.CheckArgumentNull(expression, "expression");
            type = type.AsActualTypeReference();

            // If we don't have a type to assert this passes vacuously.
            if (type == null || type.TypeKind() == EdmTypeKind.None)
            {
                discoveredErrors = Enumerable.Empty<EdmError>();
                return true;
            }

            switch (expression.ExpressionKind)
            {
                case EdmExpressionKind.IntegerConstant:
                case EdmExpressionKind.StringConstant:
                case EdmExpressionKind.BinaryConstant:
                case EdmExpressionKind.BooleanConstant:
                case EdmExpressionKind.DateTimeOffsetConstant:
                case EdmExpressionKind.DecimalConstant:
                case EdmExpressionKind.FloatingConstant:
                case EdmExpressionKind.GuidConstant:
                case EdmExpressionKind.DurationConstant:
                case EdmExpressionKind.DateConstant:
                case EdmExpressionKind.TimeOfDayConstant:
                    IEdmPrimitiveValue primitiveValue = (IEdmPrimitiveValue)expression;
                    if (primitiveValue.Type != null)
                    {
                        return TestTypeReferenceMatch(primitiveValue.Type, type, expression.Location(), matchExactly, out discoveredErrors);
                    }

                    return TryCastPrimitiveAsType(primitiveValue, type, out discoveredErrors);
                case EdmExpressionKind.Null:
                    return TryCastNullAsType((IEdmNullExpression)expression, type, out discoveredErrors);
                case EdmExpressionKind.Path:
                case EdmExpressionKind.PropertyPath:
                case EdmExpressionKind.NavigationPropertyPath:
                    return TryCastPathAsType((IEdmPathExpression)expression, type, context, matchExactly, out discoveredErrors);
                case EdmExpressionKind.OperationApplication:
                    IEdmApplyExpression applyExpression = (IEdmApplyExpression)expression;
                    if (applyExpression.AppliedOperation != null)
                    {
                        IEdmOperation operation = applyExpression.AppliedOperation as IEdmOperation;
                        if (operation != null)
                        {
                            return TestTypeReferenceMatch(operation.ReturnType, type, expression.Location(), matchExactly, out discoveredErrors);
                        }
                    }

                    // If we don't have the applied function we just assume that it will work.
                    discoveredErrors = Enumerable.Empty<EdmError>();
                    return true;
                case EdmExpressionKind.If:
                    return TryCastIfAsType((IEdmIfExpression)expression, type, context, matchExactly, out discoveredErrors);
                case EdmExpressionKind.IsType:
                    return TestTypeReferenceMatch(EdmCoreModel.Instance.GetBoolean(false), type, expression.Location(), matchExactly, out discoveredErrors);
                case EdmExpressionKind.Record:
                    IEdmRecordExpression recordExpression = (IEdmRecordExpression)expression;
                    if (recordExpression.DeclaredType != null)
                    {
                        return TestTypeReferenceMatch(recordExpression.DeclaredType, type, expression.Location(), matchExactly, out discoveredErrors);
                    }

                    return TryCastRecordAsType(recordExpression, type, context, matchExactly, out discoveredErrors);
                case EdmExpressionKind.Collection:
                    IEdmCollectionExpression collectionExpression = (IEdmCollectionExpression)expression;
                    if (collectionExpression.DeclaredType != null)
                    {
                        return TestTypeReferenceMatch(collectionExpression.DeclaredType, type, expression.Location(), matchExactly, out discoveredErrors);
                    }

                    return TryCastCollectionAsType(collectionExpression, type, context, matchExactly, out discoveredErrors);
                case EdmExpressionKind.Labeled:
                    return TryCast(((IEdmLabeledExpression)expression).Expression, type, context, matchExactly, out discoveredErrors);
                case EdmExpressionKind.Cast:
                    return TestTypeReferenceMatch(((IEdmCastExpression)expression).Type, type, expression.Location(), matchExactly, out discoveredErrors);
                case EdmExpressionKind.LabeledExpressionReference:
                    return TryCast(((IEdmLabeledExpressionReferenceExpression)expression).ReferencedLabeledExpression, type, out discoveredErrors);
                default:
                    discoveredErrors = new EdmError[] { new EdmError(expression.Location(), EdmErrorCode.ExpressionNotValidForTheAssertedType, Edm.Strings.EdmModel_Validator_Semantic_ExpressionNotValidForTheAssertedType) };
                    return false;
            }
        }
Example #17
0
        /// <summary>
        /// Determines if the type of an expression is compatible with the provided type
        /// </summary>
        /// <param name="expression">The expression to assert the type of.</param>
        /// <param name="type">The type to assert the expression as.</param>
        /// <param name="context">The context paths are to be evaluated in.</param>
        /// <param name="matchExactly">A value indicating whether the expression must match the asserted type exactly, or simply be compatible.</param>
        /// <param name="discoveredErrors">Errors produced if the expression does not match the specified type.</param>
        /// <returns>A value indicating whether the expression is valid for the given type or not.</returns>
        /// <remarks>If the expression has an associated type, this function will check that it matches the expected type and stop looking further.
        /// If an expression claims a type, it must be validated that the type is valid for the expression. If the expression does not claim a type
        /// this method will attempt to check the validity of the expression itself with the asserted type.</remarks>
        public static bool TryCast(this IEdmExpression expression, IEdmTypeReference type, IEdmType context, bool matchExactly, out IEnumerable <EdmError> discoveredErrors)
        {
            EdmUtil.CheckArgumentNull(expression, "expression");
            type = type.AsActualTypeReference();

            // If we don't have a type to assert this passes vacuously.
            if (type == null || type.TypeKind() == EdmTypeKind.None)
            {
                discoveredErrors = Enumerable.Empty <EdmError>();
                return(true);
            }

            switch (expression.ExpressionKind)
            {
            case EdmExpressionKind.IntegerConstant:
            case EdmExpressionKind.StringConstant:
            case EdmExpressionKind.BinaryConstant:
            case EdmExpressionKind.BooleanConstant:
            case EdmExpressionKind.DateTimeOffsetConstant:
            case EdmExpressionKind.DecimalConstant:
            case EdmExpressionKind.FloatingConstant:
            case EdmExpressionKind.GuidConstant:
            case EdmExpressionKind.DurationConstant:
            case EdmExpressionKind.DateConstant:
            case EdmExpressionKind.TimeOfDayConstant:
                IEdmPrimitiveValue primitiveValue = (IEdmPrimitiveValue)expression;
                if (primitiveValue.Type != null)
                {
                    return(TestTypeReferenceMatch(primitiveValue.Type, type, expression.Location(), matchExactly, out discoveredErrors));
                }

                return(TryCastPrimitiveAsType(primitiveValue, type, out discoveredErrors));

            case EdmExpressionKind.Null:
                return(TryCastNullAsType((IEdmNullExpression)expression, type, out discoveredErrors));

            case EdmExpressionKind.Path:
            case EdmExpressionKind.PropertyPath:
            case EdmExpressionKind.NavigationPropertyPath:
            case EdmExpressionKind.AnnotationPath:
                return(TryCastPathAsType((IEdmPathExpression)expression, type, context, matchExactly, out discoveredErrors));

            case EdmExpressionKind.FunctionApplication:
                IEdmApplyExpression applyExpression = (IEdmApplyExpression)expression;
                if (applyExpression.AppliedFunction != null)
                {
                    IEdmOperation operation = applyExpression.AppliedFunction as IEdmOperation;
                    if (operation != null)
                    {
                        return(TestTypeReferenceMatch(operation.ReturnType, type, expression.Location(), matchExactly, out discoveredErrors));
                    }
                }

                // If we don't have the applied function we just assume that it will work.
                discoveredErrors = Enumerable.Empty <EdmError>();
                return(true);

            case EdmExpressionKind.If:
                return(TryCastIfAsType((IEdmIfExpression)expression, type, context, matchExactly, out discoveredErrors));

            case EdmExpressionKind.IsType:
                return(TestTypeReferenceMatch(EdmCoreModel.Instance.GetBoolean(false), type, expression.Location(), matchExactly, out discoveredErrors));

            case EdmExpressionKind.Record:
                IEdmRecordExpression recordExpression = (IEdmRecordExpression)expression;
                if (recordExpression.DeclaredType != null)
                {
                    return(TestTypeReferenceMatch(recordExpression.DeclaredType, type, expression.Location(), matchExactly, out discoveredErrors));
                }

                return(TryCastRecordAsType(recordExpression, type, context, matchExactly, out discoveredErrors));

            case EdmExpressionKind.Collection:
                IEdmCollectionExpression collectionExpression = (IEdmCollectionExpression)expression;
                if (collectionExpression.DeclaredType != null)
                {
                    return(TestTypeReferenceMatch(collectionExpression.DeclaredType, type, expression.Location(), matchExactly, out discoveredErrors));
                }

                return(TryCastCollectionAsType(collectionExpression, type, context, matchExactly, out discoveredErrors));

            case EdmExpressionKind.Labeled:
                return(TryCast(((IEdmLabeledExpression)expression).Expression, type, context, matchExactly, out discoveredErrors));

            case EdmExpressionKind.Cast:
                return(TestTypeReferenceMatch(((IEdmCastExpression)expression).Type, type, expression.Location(), matchExactly, out discoveredErrors));

            case EdmExpressionKind.LabeledExpressionReference:
                return(TryCast(((IEdmLabeledExpressionReferenceExpression)expression).ReferencedLabeledExpression, type, out discoveredErrors));

            case EdmExpressionKind.EnumMember:
                return(TryCastEnumConstantAsType((IEdmEnumMemberExpression)expression, type, matchExactly, out discoveredErrors));

            default:
                discoveredErrors = new EdmError[] { new EdmError(expression.Location(), EdmErrorCode.ExpressionNotValidForTheAssertedType, Edm.Strings.EdmModel_Validator_Semantic_ExpressionNotValidForTheAssertedType) };
                return(false);
            }
        }
Example #18
0
        internal static bool ValidateValueCanBeWrittenAsXmlElementAnnotation(IEdmValue value, string annotationNamespace, string annotationName, out EdmError error)
        {
            IEdmStringValue edmStringValue = value as IEdmStringValue;

            if (edmStringValue == null)
            {
                error = new EdmError(value.Location(), EdmErrorCode.InvalidElementAnnotation, Edm.Strings.EdmModel_Validator_Semantic_InvalidElementAnnotationNotIEdmStringValue);
                return(false);
            }

            string rawString = edmStringValue.Value;

            XmlReader reader = XmlReader.Create(new StringReader(rawString));

            try
            {
                // Skip to root element.
                if (reader.NodeType != XmlNodeType.Element)
                {
                    while (reader.Read() && reader.NodeType != XmlNodeType.Element)
                    {
                    }
                }

                // The annotation must be an element.
                if (reader.EOF)
                {
                    error = new EdmError(value.Location(), EdmErrorCode.InvalidElementAnnotation, Edm.Strings.EdmModel_Validator_Semantic_InvalidElementAnnotationValueInvalidXml);
                    return(false);
                }

                // The root element must corespond to the term of the annotation
                string elementNamespace = reader.NamespaceURI;
                string elementName      = reader.LocalName;

                if (EdmUtil.IsNullOrWhiteSpaceInternal(elementNamespace) || EdmUtil.IsNullOrWhiteSpaceInternal(elementName))
                {
                    error = new EdmError(value.Location(), EdmErrorCode.InvalidElementAnnotation, Edm.Strings.EdmModel_Validator_Semantic_InvalidElementAnnotationNullNamespaceOrName);
                    return(false);
                }

                if (!((annotationNamespace == null || elementNamespace == annotationNamespace) && (annotationName == null || elementName == annotationName)))
                {
                    error = new EdmError(value.Location(), EdmErrorCode.InvalidElementAnnotation, Edm.Strings.EdmModel_Validator_Semantic_InvalidElementAnnotationMismatchedTerm);
                    return(false);
                }

                // Parse the entire fragment to determine if the XML is valid
                while (reader.Read())
                {
                }

                error = null;
                return(true);
            }
            catch (XmlException)
            {
                error = new EdmError(value.Location(), EdmErrorCode.InvalidElementAnnotation, Edm.Strings.EdmModel_Validator_Semantic_InvalidElementAnnotationValueInvalidXml);
                return(false);
            }
        }
Example #19
0
 internal static bool IsInterfaceCritical(EdmError error)
 {
     return(error.ErrorCode >= EdmErrorCode.InterfaceCriticalPropertyValueMustNotBeNull && error.ErrorCode <= EdmErrorCode.InterfaceCriticalCycleInTypeHierarchy);
 }
        private static bool TryCastIntegerConstantInRange(IEdmIntegerConstantExpression expression, long min, long max, out IEnumerable<EdmError> discoveredErrors)
        {
            if (expression.Value < min || expression.Value > max)
            {
                discoveredErrors = new EdmError[] { new EdmError(expression.Location(), EdmErrorCode.IntegerConstantValueOutOfRange, Edm.Strings.EdmModel_Validator_Semantic_IntegerConstantValueOutOfRange) };
                return false;
            }

            discoveredErrors = Enumerable.Empty<EdmError>();
            return true;
        }
        internal static bool TryCastPrimitiveAsType(this IEdmPrimitiveValue expression, IEdmTypeReference type, out IEnumerable<EdmError> discoveredErrors)
        {
            if (!type.IsPrimitive())
            {
                discoveredErrors = new EdmError[] { new EdmError(expression.Location(), EdmErrorCode.PrimitiveConstantExpressionNotValidForNonPrimitiveType, Edm.Strings.EdmModel_Validator_Semantic_PrimitiveConstantExpressionNotValidForNonPrimitiveType) };
                return false;
            }

            switch (expression.ValueKind)
            {
                case EdmValueKind.Binary:
                    return TryCastBinaryConstantAsType((IEdmBinaryConstantExpression)expression, type, out discoveredErrors);
                case EdmValueKind.Boolean:
                    return TryCastBooleanConstantAsType((IEdmBooleanConstantExpression)expression, type, out discoveredErrors);
                case EdmValueKind.DateTimeOffset:
                    return TryCastDateTimeOffsetConstantAsType((IEdmDateTimeOffsetConstantExpression)expression, type, out discoveredErrors);
                case EdmValueKind.Decimal:
                    return TryCastDecimalConstantAsType((IEdmDecimalConstantExpression)expression, type, out discoveredErrors);
                case EdmValueKind.Floating:
                    return TryCastFloatingConstantAsType((IEdmFloatingConstantExpression)expression, type, out discoveredErrors);
                case EdmValueKind.Guid:
                    return TryCastGuidConstantAsType((IEdmGuidConstantExpression)expression, type, out discoveredErrors);
                case EdmValueKind.Integer:
                    return TryCastIntegerConstantAsType((IEdmIntegerConstantExpression)expression, type, out discoveredErrors);
                case EdmValueKind.String:
                    return TryCastStringConstantAsType((IEdmStringConstantExpression)expression, type, out discoveredErrors);
                case EdmValueKind.Duration:
                    return TryCastDurationConstantAsType((IEdmDurationConstantExpression)expression, type, out discoveredErrors);
                case EdmValueKind.Date:
                    return TryCastDateConstantAsType((IEdmDateConstantExpression)expression, type, out discoveredErrors);
                case EdmValueKind.TimeOfDay:
                    return TryCastTimeOfDayConstantAsType((IEdmTimeOfDayConstantExpression)expression, type, out discoveredErrors);
                default:
                    discoveredErrors = new EdmError[] { new EdmError(expression.Location(), EdmErrorCode.ExpressionPrimitiveKindNotValidForAssertedType, Edm.Strings.EdmModel_Validator_Semantic_ExpressionPrimitiveKindNotValidForAssertedType) };
                    return false;
            }
        }
        private static bool TryCastBinaryConstantAsType(IEdmBinaryConstantExpression expression, IEdmTypeReference type, out IEnumerable<EdmError> discoveredErrors)
        {
            if (!type.IsBinary())
            {
                discoveredErrors = new EdmError[] { new EdmError(expression.Location(), EdmErrorCode.ExpressionPrimitiveKindNotValidForAssertedType, Edm.Strings.EdmModel_Validator_Semantic_ExpressionPrimitiveKindNotValidForAssertedType) };
                return false;
            }

            IEdmBinaryTypeReference binaryType = type.AsBinary();
            if (binaryType.MaxLength.HasValue && expression.Value.Length > binaryType.MaxLength.Value)
            {
                discoveredErrors = new EdmError[] { new EdmError(expression.Location(), EdmErrorCode.BinaryConstantLengthOutOfRange, Edm.Strings.EdmModel_Validator_Semantic_BinaryConstantLengthOutOfRange(expression.Value.Length, binaryType.MaxLength.Value)) };
                return false;
            }

            discoveredErrors = Enumerable.Empty<EdmError>();
            return true;
        }
        internal static bool TryCastNullAsType(this IEdmNullExpression expression, IEdmTypeReference type, out IEnumerable<EdmError> discoveredErrors)
        {
            if (!type.IsNullable)
            {
                discoveredErrors = new EdmError[] { new EdmError(expression.Location(), EdmErrorCode.NullCannotBeAssertedToBeANonNullableType, Edm.Strings.EdmModel_Validator_Semantic_NullCannotBeAssertedToBeANonNullableType) };
                return false;
            }

            discoveredErrors = Enumerable.Empty<EdmError>();
            return true;
        }
        private static bool TestTypeMatch(this IEdmType expressionType, IEdmType assertedType, EdmLocation location, bool matchExactly, out IEnumerable<EdmError> discoveredErrors)
        {
            if (matchExactly)
            {
                if (!expressionType.IsEquivalentTo(assertedType))
                {
                    discoveredErrors = new EdmError[] { new EdmError(location, EdmErrorCode.ExpressionNotValidForTheAssertedType, Edm.Strings.EdmModel_Validator_Semantic_ExpressionNotValidForTheAssertedType) };
                    return false;
                }
            }
            else
            {
                // A bad type matches anything (so as to avoid generating spurious errors).
                if (expressionType.TypeKind == EdmTypeKind.None || expressionType.IsBad())
                {
                    discoveredErrors = Enumerable.Empty<EdmError>();
                    return true;
                }

                if (expressionType.TypeKind == EdmTypeKind.Primitive && assertedType.TypeKind == EdmTypeKind.Primitive)
                {
                    IEdmPrimitiveType primitiveExpressionType = expressionType as IEdmPrimitiveType;
                    IEdmPrimitiveType primitiveAssertedType = assertedType as IEdmPrimitiveType;
                    if (!primitiveExpressionType.PrimitiveKind.PromotesTo(primitiveAssertedType.PrimitiveKind))
                    {
                        discoveredErrors = new EdmError[] { new EdmError(location, EdmErrorCode.ExpressionPrimitiveKindNotValidForAssertedType, Edm.Strings.EdmModel_Validator_Semantic_ExpressionPrimitiveKindCannotPromoteToAssertedType(expressionType.ToTraceString(), assertedType.ToTraceString())) };
                        return false;
                    }
                }
                else
                {
                    if (!expressionType.IsOrInheritsFrom(assertedType))
                    {
                        discoveredErrors = new EdmError[] { new EdmError(location, EdmErrorCode.ExpressionNotValidForTheAssertedType, Edm.Strings.EdmModel_Validator_Semantic_ExpressionNotValidForTheAssertedType) };
                        return false;
                    }
                }
            }

            discoveredErrors = Enumerable.Empty<EdmError>();
            return true;
        }
        internal static bool TryCastPathAsType(this IEdmPathExpression expression, IEdmTypeReference type, IEdmType context, bool matchExactly, out IEnumerable<EdmError> discoveredErrors)
        {
            IEdmStructuredType structuredContext = context as IEdmStructuredType;
            if (structuredContext != null)
            {
                IEdmType result = context;

                // [EdmLib] Need to handle paths that bind to things other than properties.
                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;
        }
        internal static bool SignificantToSerialization(EdmError error)
        {
            if (ValidationHelper.IsInterfaceCritical(error))
            {
                return true;
            }

            switch (error.ErrorCode)
            {
                case EdmErrorCode.InvalidName:
                case EdmErrorCode.NameTooLong:
                case EdmErrorCode.InvalidNamespaceName:
                case EdmErrorCode.SystemNamespaceEncountered:
                case EdmErrorCode.ReferencedTypeMustHaveValidName:
                case EdmErrorCode.OperationImportEntitySetExpressionIsInvalid:
                case EdmErrorCode.OperationImportParameterIncorrectType:
                case EdmErrorCode.InvalidOperationImportParameterMode:
                case EdmErrorCode.TypeMustNotHaveKindOfNone:
                case EdmErrorCode.PrimitiveTypeMustNotHaveKindOfNone:
                case EdmErrorCode.PropertyMustNotHaveKindOfNone:
                case EdmErrorCode.TermMustNotHaveKindOfNone:
                case EdmErrorCode.SchemaElementMustNotHaveKindOfNone:
                case EdmErrorCode.EntityContainerElementMustNotHaveKindOfNone:
                case EdmErrorCode.BinaryValueCannotHaveEmptyValue:
                case EdmErrorCode.EnumMustHaveIntegerUnderlyingType:
                case EdmErrorCode.EnumMemberTypeMustMatchEnumUnderlyingType:
                    return true;
            }

            return false;
        }
Example #27
0
 /// <summary>
 /// Register an error with the validation context.
 /// </summary>
 /// <param name="error">Error to register.</param>
 public void AddError(EdmError error)
 {
     this.errors.Add(error);
 }