/// <summary> /// Validates whether facets are declared correctly. /// </summary> /// <param name="element"> Schema element being validated. Must not be null. </param> /// <param name="type"> Resolved type (from declaration on the element). Possibly null. </param> /// <param name="typeUsageBuilder"> TypeUsageBuilder for the current element. Must not be null. </param> internal static void ValidateFacets(SchemaElement element, SchemaType type, TypeUsageBuilder typeUsageBuilder) { Debug.Assert(element != null); Debug.Assert(typeUsageBuilder != null); if (type != null) { var schemaEnumType = type as SchemaEnumType; if (schemaEnumType != null) { typeUsageBuilder.ValidateEnumFacets(schemaEnumType); } else if (!(type is ScalarType) && typeUsageBuilder.HasUserDefinedFacets) { Debug.Assert(!(type is SchemaEnumType), "Note that enums should have already been handled."); // Non-scalar type should not have Facets. element.AddError( ErrorCode.FacetOnNonScalarType, EdmSchemaErrorSeverity.Error, Strings.FacetsOnNonScalarType(type.FQName)); } } else { if (typeUsageBuilder.HasUserDefinedFacets) { // Type attribute not specified but facets exist. element.AddError( ErrorCode.IncorrectlyPlacedFacet, EdmSchemaErrorSeverity.Error, Strings.FacetDeclarationRequiresTypeAttribute); } } }
internal static string GetTypeNameForErrorMessage(SchemaType type, CollectionKind colKind, bool isRef) { var typeName = type.FQName; if (isRef) { typeName = "Ref(" + typeName + ")"; } switch (colKind) { case CollectionKind.Bag: typeName = "Collection(" + typeName + ")"; break; default: Debug.Assert(colKind == CollectionKind.None, "Unexpected CollectionKind"); break; } return typeName; }
/// <summary> /// Validated whether a type is declared correctly. /// </summary> /// <param name="element"> Schema element being validated. Must not be null. </param> /// <param name="type"> Resolved type (from declaration on the element). Possibly null. </param> /// <param name="typeSubElement"> Child schema element. Possibly null. </param> /// <remarks> /// For some elements (e.g. ReturnType) we allow the type to be defined inline in an attribute on the element itself or /// by using nested elements. These definitions are mutually exclusive. /// </remarks> internal static void ValidateTypeDeclaration(SchemaElement element, SchemaType type, SchemaElement typeSubElement) { Debug.Assert(element != null); if (type == null && typeSubElement == null) { //Type not declared as either attribute or subelement element.AddError(ErrorCode.TypeNotDeclared, EdmSchemaErrorSeverity.Error, Strings.TypeMustBeDeclared); } if (type != null && typeSubElement != null) { //Both attribute and sub-element declarations exist element.AddError( ErrorCode.TypeDeclaredAsAttributeAndElement, EdmSchemaErrorSeverity.Error, Strings.TypeDeclaredAsAttributeAndElement); } }
internal void ValidateDefaultValue(SchemaType type) { if (null == _default) { return; } var scalar = type as ScalarType; if (null != scalar) { ValidateScalarMemberDefaultValue(scalar); } else { _element.AddError(ErrorCode.DefaultNotAllowed, EdmSchemaErrorSeverity.Error, Strings.DefaultNotAllowed); } }
/// <summary> /// Resolve the type - if the type is not found, return appropriate error /// </summary> /// <returns> </returns> public bool TryResolveType(string namespaceName, string typeName, out SchemaType schemaType) { // For resolving entity container names, namespace can be null var fullyQualifiedName = String.IsNullOrEmpty(namespaceName) ? typeName : namespaceName + "." + typeName; schemaType = SchemaTypes.LookUpEquivalentKey(fullyQualifiedName); if (schemaType != null) { return true; } return false; }
internal override void ResolveTopLevelNames() { // if the underlying type was not specified in the CSDL we use int by default if (_unresolvedUnderlyingTypeName == null) { _underlyingType = Schema.SchemaManager.SchemaTypes .Single(t => t is ScalarType && ((ScalarType)t).TypeKind == PrimitiveTypeKind.Int32); } else { Debug.Assert(_unresolvedUnderlyingTypeName != string.Empty); Schema.ResolveTypeName(this, _unresolvedUnderlyingTypeName, out _underlyingType); } }
/// <summary> /// validate the following negative scenarios: /// ReturnType="Collection(EntityTypeA)" /// ReturnType="Collection(EntityTypeA)" EntitySet="ESet.EType is not oftype EntityTypeA" /// EntitySet="A" /// ReturnType="Collection(ComplexTypeA)" EntitySet="something" /// ReturnType="Collection(ComplexTypeA)", but the ComplexTypeA has a nested complexType property, this scenario will be handle in the runtime /// </summary> private void ValidateFunctionImportReturnType( SchemaElement owner, SchemaType returnType, EntityContainerEntitySet entitySet, bool entitySetPathDefined) { // If entity type, verify specification of entity set and that the type is appropriate for the entity set var entityType = returnType as SchemaEntityType; if (entitySet != null && entitySetPathDefined) { owner.AddError( ErrorCode.FunctionImportEntitySetAndEntitySetPathDeclared, EdmSchemaErrorSeverity.Error, Strings.FunctionImportEntitySetAndEntitySetPathDeclared(FQName)); } if (null != entityType) { // entity type if (null == entitySet) { // ReturnType="Collection(EntityTypeA)" owner.AddError( ErrorCode.FunctionImportReturnsEntitiesButDoesNotSpecifyEntitySet, EdmSchemaErrorSeverity.Error, Strings.FunctionImportReturnEntitiesButDoesNotSpecifyEntitySet(FQName)); } else if (null != entitySet.EntityType && !entityType.IsOfType(entitySet.EntityType)) { // ReturnType="Collection(EntityTypeA)" EntitySet="ESet.EType is not oftype EntityTypeA" owner.AddError( ErrorCode.FunctionImportEntityTypeDoesNotMatchEntitySet, EdmSchemaErrorSeverity.Error, Strings.FunctionImportEntityTypeDoesNotMatchEntitySet( FQName, entitySet.EntityType.FQName, entitySet.Name)); } } else { // complex type var complexType = returnType as SchemaComplexType; if (complexType != null) { if (entitySet != null || entitySetPathDefined) { // ReturnType="Collection(ComplexTypeA)" EntitySet="something" owner.AddError( ErrorCode.ComplexTypeAsReturnTypeAndDefinedEntitySet, EdmSchemaErrorSeverity.Error, owner.LineNumber, owner.LinePosition, Strings.ComplexTypeAsReturnTypeAndDefinedEntitySet(FQName, complexType.Name)); } } else { Debug.Assert( returnType == null || returnType is ScalarType || returnType is SchemaEnumType || returnType is Relationship, "null return type, scalar return type, enum return type or relationship expected here."); // scalar type or no return type if (entitySet != null || entitySetPathDefined) { // EntitySet="A" owner.AddError( ErrorCode.FunctionImportSpecifiesEntitySetButDoesNotReturnEntityType, EdmSchemaErrorSeverity.Error, Strings.FunctionImportSpecifiesEntitySetButNotEntityType(FQName)); } } } }
private bool ReturnTypeMeetsFunctionImportBasicRequirements(SchemaType type, CollectionKind returnTypeCollectionKind) { if (type is ScalarType && returnTypeCollectionKind == CollectionKind.Bag) { return true; } if (type is SchemaEntityType && returnTypeCollectionKind == CollectionKind.Bag) { return true; } if (Schema.SchemaVersion == XmlConstants.EdmVersionForV1_1) { if (type is ScalarType && returnTypeCollectionKind == CollectionKind.None) { return true; } if (type is SchemaEntityType && returnTypeCollectionKind == CollectionKind.None) { return true; } if (type is SchemaComplexType && returnTypeCollectionKind == CollectionKind.None) { return true; } if (type is SchemaComplexType && returnTypeCollectionKind == CollectionKind.Bag) { return true; } } if (Schema.SchemaVersion >= XmlConstants.EdmVersionForV2) { if (type is SchemaComplexType && returnTypeCollectionKind == CollectionKind.Bag) { return true; } } if (Schema.SchemaVersion >= XmlConstants.EdmVersionForV3) { if (type is SchemaEnumType && returnTypeCollectionKind == CollectionKind.Bag) { return true; } } return false; }
private void ValidateFunctionImportReturnType( SchemaElement owner, SchemaType returnType, CollectionKind returnTypeCollectionKind, EntityContainerEntitySet entitySet, bool entitySetPathDefined) { if (returnType != null && !ReturnTypeMeetsFunctionImportBasicRequirements(returnType, returnTypeCollectionKind)) { owner.AddError( ErrorCode.FunctionImportUnsupportedReturnType, EdmSchemaErrorSeverity.Error, owner, GetReturnTypeErrorMessage(Name) ); } ValidateFunctionImportReturnType(owner, returnType, entitySet, entitySetPathDefined); }
/// <summary> /// /// </summary> internal override void ResolveTopLevelNames() { base.ResolveTopLevelNames(); if (_type != null) { return; } _type = ResolveType(UnresolvedType); _typeUsageBuilder.ValidateDefaultValue(_type); var scalar = _type as ScalarType; if (scalar != null) { _typeUsageBuilder.ValidateAndSetTypeUsage(scalar, true); } }
/// <summary> /// Validate that reference type is an entity type. /// </summary> /// <param name="element"> Schema element being validated. Must not be null. </param> /// <param name="type"> Resolved type (from declaration on the element). Possibly null. </param> internal static void ValidateRefType(SchemaElement element, SchemaType type) { Debug.Assert(element != null); if (type != null && !(type is SchemaEntityType)) { // Ref type refers to non entity type. element.AddError( ErrorCode.ReferenceToNonEntityType, EdmSchemaErrorSeverity.Error, Strings.ReferenceToNonEntityType(type.FQName)); } }
/// <summary> /// Look up a fully qualified type name reference. /// </summary> /// <param name="usingElement">element containing the reference</param> /// <param name="typeName">the fully qualified type name</param> /// <param name="type">the referenced schema type</param> /// <returns>false if there was an error</returns> internal bool ResolveTypeName(SchemaElement usingElement, string typeName, out SchemaType type) { Debug.Assert(usingElement != null); Debug.Assert(typeName != null); type = null; // get the schema(s) that match the namespace/alias string actualQualification; string unqualifiedTypeName; Utils.ExtractNamespaceAndName(typeName, out actualQualification, out unqualifiedTypeName); var definingQualification = actualQualification; if (definingQualification == null) { definingQualification = ProviderManifest == null ? _namespaceName : ProviderManifest.NamespaceName; } string namespaceName; // First check if there is an alias defined by this name. For primitive type namespace, we do not need to resolve // any alias, since that's a reserved keyword and we don't allow alias with that name if (actualQualification == null || !AliasResolver.TryResolveAlias(definingQualification, out namespaceName)) { namespaceName = definingQualification; } // Resolve the type name if (!SchemaManager.TryResolveType(namespaceName, unqualifiedTypeName, out type)) { // it must be an undefined type. if (actualQualification == null) { // Every type except the primitive type must be qualified usingElement.AddError(ErrorCode.NotInNamespace, EdmSchemaErrorSeverity.Error, Strings.NotNamespaceQualified(typeName)); } else if (!SchemaManager.IsValidNamespaceName(namespaceName)) { usingElement.AddError( ErrorCode.BadNamespace, EdmSchemaErrorSeverity.Error, Strings.BadNamespaceOrAlias(actualQualification)); } else { // if the type name was alias qualified if (namespaceName != definingQualification) { usingElement.AddError( ErrorCode.NotInNamespace, EdmSchemaErrorSeverity.Error, Strings.NotInNamespaceAlias(unqualifiedTypeName, namespaceName, definingQualification)); } else { usingElement.AddError( ErrorCode.NotInNamespace, EdmSchemaErrorSeverity.Error, Strings.NotInNamespaceNoAlias(unqualifiedTypeName, namespaceName)); } } return false; } // For ssdl and provider manifest, make sure that the type is present in this schema or primitive schema else if (DataModel != SchemaDataModelOption.EntityDataModel && type.Schema != this && type.Schema != SchemaManager.PrimitiveSchema) { Debug.Assert(type.Namespace != Namespace, "Using element is not allowed in the schema of ssdl and provider manifest"); usingElement.AddError( ErrorCode.InvalidNamespaceOrAliasSpecified, EdmSchemaErrorSeverity.Error, Strings.InvalidNamespaceOrAliasSpecified(actualQualification)); return false; } return true; }
protected void TryAddContainer(SchemaType schemaType, bool doNotAddErrorForEmptyName) { SchemaManager.SchemaTypes.Add( schemaType, doNotAddErrorForEmptyName, Strings.EntityContainerAlreadyExists); SchemaTypes.Add(schemaType); }
protected void TryAddType(SchemaType schemaType, bool doNotAddErrorForEmptyName) { SchemaManager.SchemaTypes.Add( schemaType, doNotAddErrorForEmptyName, Strings.TypeNameAlreadyDefinedDuplicate); SchemaTypes.Add(schemaType); }