/// <summary> /// Performs the fixup for all items that have Name and Namespace. /// </summary> /// <param name="model">Model to perform fixup on.</param> public void Fixup(EntityModelSchema model) { foreach (INamedItem item in this.GetAllNamedItems(model)) { this.FixupNamedItem(item); } }
/// <summary> /// Applies default namespace to all items in the model that don't have one. /// </summary> /// <param name="schema">Schema to fixup.</param> /// <param name="defaultNamespaceName">Default namespace to apply.</param> /// <returns>This instance (can be used to chain calls together)</returns> public static EntityModelSchema ApplyDefaultNamespace(this EntityModelSchema schema, string defaultNamespaceName) { var fixup = new ApplyDefaultNamespaceFixup(defaultNamespaceName); fixup.Fixup(schema); return(schema); }
/// <summary> /// Converts a model from Taupo term into Edm term /// </summary> /// <param name="taupoModel">The input model in Taupo term</param> /// <returns>The output model in Edm term</returns> public IEdmModel ConvertToEdmModel(EntityModelSchema taupoModel) { IEnumerable<XElement> csdlElements = this.GenerateCsdlElements(taupoModel); IEdmModel resultEdmModel = this.GetParserResult(csdlElements); return resultEdmModel; }
/// <summary> /// Compares the two models to each other and throws an exception when there is an erro /// </summary> /// <param name="expectedTestEntityModel">EntityModelSchema to compare y to</param> /// <param name="actualEntityModelSchema">EntityModelSchema to compare x to</param> /// <returns>List of errors</returns> public ICollection<string> Compare(EntityModelSchema expectedTestEntityModel, EntityModelSchema actualEntityModelSchema) { this.errors = new List<string>(); foreach (ComplexType complexType in expectedTestEntityModel.ComplexTypes) { List<ComplexType> complexTypes = actualEntityModelSchema.ComplexTypes.Where(ct => ct.FullName == complexType.FullName).ToList(); if (!this.WriteErrorIfFalse(complexTypes.Count == 1, "Cannot find complexType '{0}'", complexType.Name)) { ComplexType ycomplexType = complexTypes.Single(); this.CompareComplexType(complexType, ycomplexType); } } foreach (EntityType expectedEntityType in expectedTestEntityModel.EntityTypes) { List<EntityType> entityTypes = actualEntityModelSchema.EntityTypes.Where(et => et.FullName == expectedEntityType.FullName).ToList(); if (!this.WriteErrorIfFalse(entityTypes.Count == 1, "Cannot find entityType '{0}'", expectedEntityType.Name)) { EntityType actualEntityType = entityTypes.Single(); this.CompareEntityTypes(expectedEntityType, actualEntityType); } } foreach (EntityContainer expectedEntityContainer in expectedTestEntityModel.EntityContainers) { List<EntityContainer> entityContainers = actualEntityModelSchema.EntityContainers.Where(ec => ec.Name == expectedEntityContainer.Name).ToList(); if (!this.WriteErrorIfFalse(entityContainers.Count == 1, "Cannot find entityContainer '{0}'", expectedEntityContainer.Name)) { EntityContainer actualEntityContainer = entityContainers.Single(); this.CompareEntityContainer(expectedEntityContainer, actualEntityContainer); } } return this.errors; }
/// <summary> /// Adds the EntitySet information to an action or validates that it has an entitySet Path /// </summary> /// <param name="model">The model to fix up</param> public void Fixup(EntityModelSchema model) { foreach (Function f in model.Functions.Where(f => f.IsAction() && f.ReturnType != null)) { var serviceOperationAnnotation = f.Annotations.OfType<ServiceOperationAnnotation>().Single(); // If someone has set the entitySetPath or the entitySet name then we don't need to update anything if (serviceOperationAnnotation.EntitySetPath != null || serviceOperationAnnotation.EntitySetName != null) { continue; } EntityDataType entityDataType = f.ReturnType as EntityDataType; var collectionDataType = f.ReturnType as CollectionDataType; if (collectionDataType != null) { entityDataType = collectionDataType.ElementDataType as EntityDataType; } if (entityDataType != null) { var possibleMatch = model.EntityContainers.Single().EntitySets.Where(es => entityDataType.Definition.IsKindOf(es.EntityType)).ToList(); ExceptionUtilities.Assert(possibleMatch.Count == 1, string.Format(CultureInfo.InvariantCulture, "Cannot resolve function '{0}' to one EntitySet, possible matches were '{1}'", f.Name, string.Join(",", possibleMatch.Select(es => es.Name)))); serviceOperationAnnotation.EntitySetName = possibleMatch.Single().Name; } } }
/// <summary> /// Improve the model if goal not yet met /// </summary> /// <param name="model">Model to improve</param> public override void Improve(EntityModelSchema model) { foreach (var et in model.EntityTypes .Where(c => c.BaseType == null) .Where(c => c.AllKeyProperties.Count() < this.MinNumberOfKeysPerEntities)) { int numOfKeyPropertiesNeeded = this.MinNumberOfKeysPerEntities; if (this.MinNumberOfKeysPerEntities != this.MaxNumberOfKeysPerEntities) { numOfKeyPropertiesNeeded = this.Random.NextFromRange(this.MinNumberOfKeysPerEntities, this.MaxNumberOfKeysPerEntities); } // Consume the existing properties... foreach (MemberProperty mp in et.Properties.Where(p => p.IsPrimaryKey == false).SkipWhile(q => q.PropertyType is ComplexDataType)) { if (et.AllKeyProperties.Count() < numOfKeyPropertiesNeeded) { mp.IsPrimaryKey = true; } else { break; } } // Create new properties and make them key... while (et.AllKeyProperties.Count() < numOfKeyPropertiesNeeded) { et.Properties.Add(new MemberProperty() { IsPrimaryKey = true }); } } }
/// <summary> /// Generates the object layer for the given model /// </summary> /// <param name="compileUnit">The compile unit to add code to</param> /// <param name="model">The model to base the object layer on</param> public void GenerateObjectLayer(CodeCompileUnit compileUnit, EntityModelSchema model) { var namespaces = model.EntityTypes.Select(et => et.NamespaceName).Union(model.ComplexTypes.Select(ct => ct.NamespaceName)).Union(model.Functions.Select(f => f.NamespaceName)).Distinct().ToList(); foreach (string namespaceName in namespaces) { CodeNamespace codeNamespace = Code.AddNamespace(compileUnit, namespaceName); foreach (string ns in this.GetNamespaceImports()) { codeNamespace.ImportNamespace(ns); } foreach (ComplexType type in model.ComplexTypes.Where(ct => ct.NamespaceName == namespaceName)) { if (this.ShouldGenerateTypeDefinition(type)) { this.DeclareComplexType(type, codeNamespace.DeclareType(type.Name)); } } foreach (EntityType type in model.EntityTypes.Where(ct => ct.NamespaceName == namespaceName)) { if (this.ShouldGenerateTypeDefinition(type)) { this.DeclareEntityType(type, codeNamespace.DeclareType(type.Name)); } } this.AddFunctionsInNamespaceIfRequired(namespaceName, codeNamespace, model.Functions); } }
/// <summary> /// Generates POCO entities based on the supplied model /// </summary> /// <param name="model">Model to generate classes from</param> /// <returns>Generated code files</returns> public IEnumerable<FileContents<string>> GenerateEntityClasses(EntityModelSchema model) { ExceptionUtilities.CheckArgumentNotNull(model, "model"); PocoAnnotator.Annotate(model, this.PocoOption); List<FileContents<string>> results = new List<FileContents<string>>(); foreach (var ns in model.EntityTypes.Select(e => e.NamespaceName).Concat(model.EnumTypes.Select(e => e.NamespaceName)).Concat(model.ComplexTypes.Select(e => e.NamespaceName)).Distinct()) { var codeUnit = new CodeCompileUnit(); CodeNamespace codeNamespace = codeUnit.AddNamespace(ns); codeNamespace.ImportNamespace("System.Collections.Generic"); foreach (var type in model.ComplexTypes.Where(e => e.NamespaceName == ns)) { codeNamespace.Types.Add(this.BuildType(type)); } foreach (var type in model.EntityTypes.Where(e => e.NamespaceName == ns)) { codeNamespace.Types.Add(this.BuildType(type)); } foreach (var type in model.EnumTypes.Where(e => e.NamespaceName == ns)) { codeNamespace.Types.Add(this.BuildType(type)); } string code = this.GenerateCodeFromCompileUnit(codeUnit); results.Add(new FileContents<string>(ns + this.language.FileExtension, code)); } return results; }
/// <summary> /// Visits a model /// </summary> /// <param name="model">model to visit</param> public void Visit(EntityModelSchema model) { foreach (var entity in model.EntityTypes) { this.VisitEntityType(entity); } foreach (var complex in model.ComplexTypes) { this.VisitComplexType(complex); } foreach (var association in model.Associations) { this.VisitAssociationType(association); } foreach (var container in model.EntityContainers) { this.VisitEntityContainer(container); } foreach (var function in model.Functions) { this.VisitFunction(function); } foreach (var enumType in model.EnumTypes) { this.VisitEnumType(enumType); } }
/// <summary> /// Overrides the namespace of all items in the model /// </summary> /// <param name="schema">Schema to fixup.</param> /// <param name="newNamespaceName">New namespace to apply</param> /// <returns>This instance (can be used to chain calls together)</returns> public static EntityModelSchema OverrideNamespace(this EntityModelSchema schema, string newNamespaceName) { var fixup = new OverrideNamespaceFixup(newNamespaceName); fixup.Fixup(schema); return(schema); }
/// <summary> /// Add the default container to the model /// By default is having one set for each base EntityType and AssociationType, you can opt out by adding FixupNoSetAnnotation /// </summary> /// <param name="schema">Schema to add Container</param> /// <param name="containerName">name of Container</param> /// <returns>This instance (can be used to chain calls together)</returns> public static EntityModelSchema AddDefaultContainer(this EntityModelSchema schema, string containerName) { var fixup = new AddDefaultContainerFixup(containerName); fixup.Fixup(schema); return(schema); }
/// <summary> /// Remove concurrency tokens defined on complex types and properties /// </summary> /// <param name="model">The model to fix up</param> public void Fixup(EntityModelSchema model) { foreach (var ct in model.ComplexTypes) { foreach (var property in ct.Properties) { // ToList is to avoid modifying the collection during enumeration foreach (var annotation in property.Annotations.OfType<ConcurrencyTokenAnnotation>().ToList()) { property.Annotations.Remove(annotation); } } } foreach (var et in model.EntityTypes) { foreach (var property in et.AllProperties.Where(p => p.PropertyType is ComplexDataType)) { // ToList is to avoid modifying the collection during enumeration foreach (var annotation in property.Annotations.OfType<ConcurrencyTokenAnnotation>().ToList()) { property.Annotations.Remove(annotation); } } } }
/// <summary> /// Replace binary key properties with properties of the replacement type while maintaining nullability /// </summary> /// <param name="model">The model to fix up</param> public void Fixup(EntityModelSchema model) { List<MemberProperty> modifiedProperties = new List<MemberProperty>(); foreach (var et in model.EntityTypes) { foreach (var prop in et.AllKeyProperties) { if (prop.PropertyType is BinaryDataType) { modifiedProperties.Add(prop); this.Fixup(prop); } } } if (modifiedProperties.Count > 0) { var constraints = model.Associations .Select(a => a.ReferentialConstraint) .Where(c => c != null) .Where(c => c.PrincipalProperties.Any(p => modifiedProperties.Contains(p))); foreach (var constraint in constraints) { foreach (var prop in constraint.DependentProperties) { if (prop.PropertyType is BinaryDataType) { modifiedProperties.Add(prop); this.Fixup(prop); } } } } }
/// <summary> /// Improve the model if goal not yet met /// </summary> /// <param name="model">Model to improve</param> public override void Improve(EntityModelSchema model) { foreach (var et in model.EntityTypes) { var existingComplexProperties = et.Properties.Where(p => p.PropertyType is ComplexDataType).ToList(); if (existingComplexProperties.Count >= this.MinNumberOfComplexPropertiesPerEntity) { continue; } int numOfComplexPropertiesPerEntity = this.MinNumberOfComplexPropertiesPerEntity; if (this.RandomNumberGenerator != null) { numOfComplexPropertiesPerEntity = this.RandomNumberGenerator.NextFromRange(this.MinNumberOfComplexPropertiesPerEntity, this.MaxNumberOfComplexPropertiesPerEntity); } int remaining = numOfComplexPropertiesPerEntity - existingComplexProperties.Count; for (int i = 0; i < remaining; ++i) { et.Properties.Add(new MemberProperty() { PropertyType = DataTypes.ComplexType, }); } } }
/// <summary> /// Remove navigation properties defined on derived types /// </summary> /// <param name="model">The model to fix up</param> public void Fixup(EntityModelSchema model) { foreach (var function in model.Functions.ToList().Where(f => f.Annotations.OfType<ServiceOperationAnnotation>().Any(so => so.IsAction))) { model.Remove(function); } }
/// <summary> /// This adds service operations that take arguments of type Spatial to the given model. /// </summary> /// <param name="model">The model to which the service operations will be added</param> /// <param name="runStability">The stability of the tests where this model is being used. Operations will only be added to unstable runs to prevent failures in BVTs</param> public static void AddServiceOperationsWithSpatialArguments(EntityModelSchema model, RunStability runStability) { // The run stability is a parameter to allow unit tests to call this, for code coverage if (runStability == RunStability.Unstable) { // TODO: Remove check for test stability when product supports Service Operations and Properties of Derived Types new AddRootServiceOperationsFixup().Fixup(model); // TODO: Remove check for test stability when product supports Service Operations with Spatial Arguments model.Add(CreateSimpleServiceOperation("Function00", EdmDataTypes.Geography.WithSrid(SpatialConstants.VariableSrid))); model.Add(CreateSimpleServiceOperation("Function01", EdmDataTypes.GeographyLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.Geography.WithSrid(SpatialConstants.VariableSrid))); model.Add(CreateSimpleServiceOperation("Function02", EdmDataTypes.GeographyMultiLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.Geography.WithSrid(SpatialConstants.VariableSrid))); model.Add(CreateSimpleServiceOperation("Function03", EdmDataTypes.GeographyMultiPoint.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyMultiLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.Geography.WithSrid(SpatialConstants.VariableSrid))); model.Add(CreateSimpleServiceOperation("Function04", EdmDataTypes.GeographyMultiPolygon.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyMultiPoint.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyMultiLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.Geography.WithSrid(SpatialConstants.VariableSrid))); model.Add(CreateSimpleServiceOperation("Function05", EdmDataTypes.GeographyPoint.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyMultiPolygon.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyMultiPoint.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyMultiLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.Geography.WithSrid(SpatialConstants.VariableSrid))); model.Add(CreateSimpleServiceOperation("Function06", EdmDataTypes.GeographyPolygon.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyPoint.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyMultiPolygon.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyMultiPoint.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyMultiLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.Geography.WithSrid(SpatialConstants.VariableSrid))); model.Add(CreateSimpleServiceOperation("Function07", EdmDataTypes.GeometryCollection.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyPolygon.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyPoint.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyMultiPolygon.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyMultiPoint.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyMultiLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.Geography.WithSrid(SpatialConstants.VariableSrid))); model.Add(CreateSimpleServiceOperation("Function08", EdmDataTypes.GeometryLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeometryCollection.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyPolygon.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyPoint.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyMultiPolygon.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyMultiPoint.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyMultiLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.Geography.WithSrid(SpatialConstants.VariableSrid))); model.Add(CreateSimpleServiceOperation("Function09", EdmDataTypes.GeometryMultiLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeometryLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeometryCollection.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyPolygon.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyPoint.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyMultiPolygon.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyMultiPoint.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyMultiLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.Geography.WithSrid(SpatialConstants.VariableSrid))); model.Add(CreateSimpleServiceOperation("Function10", EdmDataTypes.GeometryMultiPoint.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeometryMultiLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeometryLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeometryCollection.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyPolygon.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyPoint.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyMultiPolygon.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyMultiPoint.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyMultiLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.Geography.WithSrid(SpatialConstants.VariableSrid))); model.Add(CreateSimpleServiceOperation("Function11", EdmDataTypes.GeometryMultiPolygon.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeometryMultiPoint.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeometryMultiLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeometryLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeometryCollection.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyPolygon.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyPoint.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyMultiPolygon.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyMultiPoint.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyMultiLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.Geography.WithSrid(SpatialConstants.VariableSrid))); model.Add(CreateSimpleServiceOperation("Function12", EdmDataTypes.GeometryPoint.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeometryMultiPolygon.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeometryMultiPoint.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeometryMultiLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeometryLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeometryCollection.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyPolygon.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyPoint.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyMultiPolygon.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyMultiPoint.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyMultiLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.Geography.WithSrid(SpatialConstants.VariableSrid))); model.Add(CreateSimpleServiceOperation("Function13", EdmDataTypes.GeometryPolygon.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeometryPoint.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeometryMultiPolygon.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeometryMultiPoint.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeometryMultiLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeometryLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeometryCollection.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyPolygon.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyPoint.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyMultiPolygon.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyMultiPoint.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyMultiLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.GeographyLineString.WithSrid(SpatialConstants.VariableSrid), EdmDataTypes.Geography.WithSrid(SpatialConstants.VariableSrid))); } }
/// <summary> /// Sets the EntityContainer to default DataServiceConfiguration settings if not specified /// Default settings are all permissions for all entitysets /// All permissions for ServiceOperations /// Visible permissions for all actions /// and UseVerboseErrors = true /// </summary> /// <param name="model">The model to fix up</param> public void Fixup(EntityModelSchema model) { EntityContainer container = model.GetDefaultEntityContainer(); if (!container.Annotations.OfType<EntitySetRightsAnnotation>().Any()) { container.Annotations.Add(new EntitySetRightsAnnotation() { Value = EntitySetRights.All }); } if (!container.Annotations.OfType<ServiceOperationRightsAnnotation>().Any()) { container.Annotations.Add(new ServiceOperationRightsAnnotation() { Value = ServiceOperationRights.All }); } if (!container.Annotations.OfType<ActionOperationRightsAnnotation>().Any()) { container.Annotations.Add(new ActionOperationRightsAnnotation() { Value = ActionOperationRights.Invoke }); } DataServiceConfigurationAnnotation dataServiceConfigurationAnnotation = container.GetDataServiceConfiguration(); if (dataServiceConfigurationAnnotation == null) { dataServiceConfigurationAnnotation = new DataServiceConfigurationAnnotation(); dataServiceConfigurationAnnotation.UseVerboseErrors = true; container.Annotations.Add(dataServiceConfigurationAnnotation); } DataServiceBehaviorAnnotation dataServiceBehaviorAnnotation = container.GetDataServiceBehavior(); if (dataServiceBehaviorAnnotation == null) { dataServiceBehaviorAnnotation = new DataServiceBehaviorAnnotation(); dataServiceBehaviorAnnotation.MaxProtocolVersion = this.MaxProtocolVersion; container.Annotations.Add(dataServiceBehaviorAnnotation); } }
/// <summary> /// Improve the model if goals not yet met /// </summary> /// <param name="model">model to improve</param> public override void Improve(EntityModelSchema model) { while (model.EntityTypes.Count() < this.MinNumberOfEntities) { model.Add(new EntityType()); } }
/// <summary> /// Parses a single csdl/ssdl file. /// </summary> /// <param name="model">the entity model schema which the csdl/ssdl file parses to</param> /// <param name="schemaElement">the top level schema element in the csdl/ssdl file</param> protected virtual void ParseSingleXsdl(EntityModelSchema model, XElement schemaElement) { this.AssertXsdlElement(schemaElement, "Schema"); this.SetupNamespaceAndAliases(schemaElement); foreach (var entityContainerElement in schemaElement.Elements().Where(el => this.IsXsdlElement(el, "EntityContainer"))) { model.Add(this.ParseEntityContainer(entityContainerElement)); } foreach (var entityTypeElement in schemaElement.Elements().Where(el => this.IsXsdlElement(el, "EntityType"))) { model.Add(this.ParseEntityType(entityTypeElement)); } foreach (var associationTypeElement in schemaElement.Elements().Where(el => this.IsXsdlElement(el, "Association"))) { model.Add(this.ParseAssociation(associationTypeElement)); } foreach (var functionElement in schemaElement.Elements().Where(el => this.IsXsdlElement(el, "Function"))) { model.Add(this.ParseFunction(functionElement)); } }
/// <summary> /// Remove named streams and corresponding features in model for EF provider /// </summary> /// <param name="model">The model to fix up</param> public void Fixup(EntityModelSchema model) { foreach (var entityType in model.EntityTypes) { entityType.Properties.RemoveAll(p => p.IsStream()); } }
/// <summary> /// Add default EntityContainer to the given EntitySchemaModel /// For each base entity type, add an EntitySet /// For each association, add an AssociationSet, between two possible EntitySets /// </summary> /// <param name="model">the given EntitySchemaModel</param> public void Fixup(EntityModelSchema model) { EntityContainer container = model.EntityContainers.FirstOrDefault(); if (container == null) { container = new EntityContainer(this.DefaultContainerName); model.Add(container); } foreach (EntityType entity in model.EntityTypes.Where(e => e.BaseType == null && !container.EntitySets.Any(set => set.EntityType == e))) { if (!entity.Annotations.OfType<FixupNoSetAnnotation>().Any()) { container.Add(new EntitySet(entity.Name, entity)); } } foreach (AssociationType association in model.Associations.Where(assoc => !container.AssociationSets.Any(assocSet => assocSet.AssociationType == assoc))) { if (!association.Annotations.OfType<FixupNoSetAnnotation>().Any()) { container.Add(new AssociationSet(association.Name, association) { Ends = { new AssociationSetEnd(association.Ends[0], container.EntitySets.First(es => association.Ends[0].EntityType.IsKindOf(es.EntityType))), new AssociationSetEnd(association.Ends[1], container.EntitySets.First(es => association.Ends[1].EntityType.IsKindOf(es.EntityType))), } }); } } }
/// <summary> /// Add default Navigation Properties to the model /// By default bi-directional, you can opt out by adding FixupNoNavigationAnnotation /// </summary> /// <param name="schema">Schema to add default Navigation Properties</param> /// <returns>This instance (can be used to chain calls together)</returns> public static EntityModelSchema AddDefaultNavigationProperties(this EntityModelSchema schema) { var fixup = new AddNavigationPropertyFixup(new ConsecutiveIdentifierGenerator()); fixup.Fixup(schema); return(schema); }
/// <summary> /// Compares the two models to each other, returns a list of error messages (if any). /// </summary> /// <param name="expectedTestEntityModel">Expected EntityModelSchema.</param> /// <param name="actualEntityModelSchema">Actual EntityModelSchema.</param> /// <returns>List of errors encountered.</returns> /// <remarks> /// This is a replacement of the default EntityModelSchemaComparer (in Taupo). It does more verification than the default one. /// Ideally this should be promoted into Taupo itself (as the default implementation). /// But since Astoria functional tests depend on the default implementation already, it's wise to do it locally first, /// otherwise, it could break a lot of their tests when branch RIs /// </remarks> public ICollection<string> Compare(EntityModelSchema expectedTestEntityModel, EntityModelSchema actualEntityModelSchema) { this.errors.Clear(); this.CompareStructuralTypes(expectedTestEntityModel.ComplexTypes.Cast<NamedStructuralType>(), actualEntityModelSchema.ComplexTypes.Cast<NamedStructuralType>(), "complex"); this.CompareStructuralTypes(expectedTestEntityModel.EntityTypes.Cast<NamedStructuralType>(), actualEntityModelSchema.EntityTypes.Cast<NamedStructuralType>(), "entity"); this.SatisfiesEquals(expectedTestEntityModel.Associations.Count(), actualEntityModelSchema.Associations.Count(), "Count of Associations does not match."); foreach (AssociationType expectedAssociation in expectedTestEntityModel.Associations) { var actualAssociations = actualEntityModelSchema.Associations.Where(a => a.FullName == expectedAssociation.FullName); if (this.SatisfiesEquals(1, actualAssociations.Count(), "Should find exactly 1 association '{0}'.", expectedAssociation.FullName)) { var actualAssociation = actualAssociations.Single(); this.CompareAssociationType(expectedAssociation, actualAssociation); this.CompareAnnotations(expectedAssociation.Annotations, actualAssociation.Annotations); } } this.SatisfiesEquals(expectedTestEntityModel.EntityContainers.Count(), actualEntityModelSchema.EntityContainers.Count(), "Count of EntityContainers does not match."); foreach (EntityContainer expectedEntityContainer in expectedTestEntityModel.EntityContainers) { var actualEntityContainers = actualEntityModelSchema.EntityContainers.Where(ec => ec.Name == expectedEntityContainer.Name); if (this.SatisfiesEquals(1, actualEntityContainers.Count(), "Should find exactly 1 entityContainer '{0}'.", expectedEntityContainer.Name)) { var actualEntityContainer = actualEntityContainers.Single(); this.CompareEntityContainer(expectedEntityContainer, actualEntityContainer); this.CompareAnnotations(expectedEntityContainer.Annotations, actualEntityContainer.Annotations); } } this.SatisfiesEquals(expectedTestEntityModel.Functions.Count(), actualEntityModelSchema.Functions.Count(), "Count of Functions does not match."); foreach (Function expectedFunction in expectedTestEntityModel.Functions) { var actualFunctions = actualEntityModelSchema.Functions.Where(f => this.FunctionSignaturesAreSame(f, expectedFunction)); if (this.SatisfiesEquals(1, actualFunctions.Count(), "Should find exactly 1 function '{0}' (with parameters).", expectedFunction.FullName)) { var actualFunction = actualFunctions.Single(); this.CompareFunction(expectedFunction, actualFunction); this.CompareAnnotations(expectedFunction.Annotations, actualFunction.Annotations); } } this.SatisfiesEquals(expectedTestEntityModel.EnumTypes.Count(), actualEntityModelSchema.EnumTypes.Count(), "Count of EnumTypes does not match."); foreach (EnumType expectedEnumType in expectedTestEntityModel.EnumTypes) { var actualEnumTypes = actualEntityModelSchema.EnumTypes.Where(e => e.FullName == expectedEnumType.FullName); if (this.SatisfiesEquals(1, actualEnumTypes.Count(), "Should find exactly 1 enum type '{0}'.", expectedEnumType.FullName)) { var actualEnumType = actualEnumTypes.Single(); this.CompareEnumType(expectedEnumType, actualEnumType); this.CompareAnnotations(expectedEnumType.Annotations, actualEnumType.Annotations); } } this.CompareAnnotations(expectedTestEntityModel.Annotations, actualEntityModelSchema.Annotations); return this.errors; }
private static bool EntityContainersValid(EntityModelSchema model) { return model.EntityContainers.All( t => t.Name != null && t.EntitySets.All(p => p.Name != null) && t.AssociationSets.All(p => p.Name != null) && t.FunctionImports.All(f => f.Name != null && f.Parameters.All(p => p.Name != null))); }
/// <summary> /// Serializes the <paramref name="schema"/> in the specified <paramref name="csdlVersion"/> and returns it. /// </summary> /// <param name="csdlVersion">The CSDL version to use for serializing the entity model schema.</param> /// <param name="schema">The schema to serialize.</param> /// <returns>The serialized <paramref name="schema"/>.</returns> public IEnumerable<FileContents<XElement>> Serialize(EdmVersion csdlVersion, EntityModelSchema schema) { ExceptionUtilities.Assert(schema != null, "schema != null"); // TODO: Can we inherit from the default implemenation of the CSDL content generator instead of doing this in a separate step? schema = this.ODataAnnotationConverter.ConvertToProductAnnotations(schema); return this.BaseEntityModelSchemaSerializer.Generate(csdlVersion, schema); }
/// <summary> /// Adds contract and instance annotations to all collection properties in the model /// </summary> /// <param name="model">The model to fix up</param> public void Fixup(EntityModelSchema model) { this.ApplyEntityTypeCollectionTypes(model); this.ApplyComplexTypeCollectionTypes(model); this.ApplyFunctionCollectionTypes(model); }
/// <summary> /// Converts the <paramref name="entityModelSchema"/> to the corresponding /// <see cref="IEdmModel"/> including the OData metadata annotations. /// </summary> /// <param name="entityModelSchema">The <see cref="EntityModelSchema"/> to convert.</param> /// <param name="loadSerializableAnnotations">true if serializable annotations should be loaded into their user-friendly in-memory representation; otherwise false.</param> /// <returns>The <see cref="IEdmModel"/> instance that corresponds to the <paramref name="entityModelSchema"/>.</returns> public override IEdmModel Convert(EntityModelSchema entityModelSchema, bool loadSerializableAnnotations = true) { var model = base.Convert(entityModelSchema, loadSerializableAnnotations); // Because we have to go through Xml we cannot easily translate in-memory annotations; fix them now. ConvertInMemoryAnnotations(entityModelSchema, model); return model; }
private IEnumerable<INamedItem> GetAllNamedItems(EntityModelSchema model) { return model.EntityTypes.Cast<INamedItem>() .Concat(model.ComplexTypes.Cast<INamedItem>()) .Concat(model.Associations.Cast<INamedItem>()) .Concat(model.Functions.Cast<INamedItem>()) .Concat(model.EnumTypes.Cast<INamedItem>()) .Concat(model.EntityContainers.Cast<INamedItem>()); }
/// <summary> /// Initializes a new instance of the DataServiceVersionVerifier class /// </summary> /// <param name="model">Entity Model Schema</param> /// <param name="maxProtocolVersion">Max Protocol Version</param> public DataServiceVersionVerifier(EntityModelSchema model, DataServiceProtocolVersion maxProtocolVersion) : base() { ExceptionUtilities.CheckArgumentNotNull(model, "model"); ExceptionUtilities.Assert(maxProtocolVersion != DataServiceProtocolVersion.Unspecified, "Max protocol version cannot be unspecified"); this.maxProtocolVersion = maxProtocolVersion; this.model = model; }
/// <summary> /// Invokes each of the fixup's in the collection /// </summary> /// <param name="model">the model to fix up</param> public void Fixup(EntityModelSchema model) { ExceptionUtilities.CheckArgumentNotNull(model, "model"); foreach (var fixup in this.Fixups) { fixup.Fixup(model); } }
/// <summary> /// Replaces missing names (type, member, container and set names) with names generated by provided <see cref="IIdentifierGenerator"/>. /// </summary> /// <param name="model">Model to work on.</param> public void Fixup(EntityModelSchema model) { this.FixupEntityTypes(model.EntityTypes); this.FixupComplexTypes(model.ComplexTypes); this.FixupEntityContainers(model.EntityContainers); this.FixupAssociations(model.Associations); this.FixupFunctions(model.Functions); this.FixupEnumTypes(model.EnumTypes); }
/// <summary> /// Checks whether the Validation Rule has been met /// </summary> /// <param name="model">Model being checked</param> /// <returns> /// Returns whether validation rule has been met /// </returns> public bool IsModelValid(EntityModelSchema model) { return EntityTypesValid(model) && ComplexTypesValid(model) && AssociationTypesValid(model) && FunctionsValid(model) && EntityContainersValid(model) && EnumTypesValid(model); }
private IEnumerable<XElement> GenerateCsdlElements(EntityModelSchema taupoModel) { var taupoCsdlGen = new CsdlContentGenerator { GenerateTaupoAnnotations = this.GenerateTaupoAnnotations, IgnoreUnsupportedAnnotations = this.IgnoreUnsupportedAnnotations }; IEnumerable<FileContents<XElement>> csdlFileContents = taupoCsdlGen.Generate(this.EdmVersion, taupoModel); return csdlFileContents.Select(fc => fc.Contents); }
/// <summary> /// Improve the model if goals not yet met /// </summary> /// <param name="model">Model to improve</param> public override void Improve(EntityModelSchema model) { foreach (var et in model.ComplexTypes.Where(ct => ct.Properties.Count() < this.MinNumberOfPropertiesPerComplexType)) { while (et.Properties.Count() < this.MinNumberOfPropertiesPerComplexType) { et.Properties.Add(new MemberProperty()); } } }
/// <summary> /// Resolves named references within the schema. /// </summary> /// <param name="schema">Schema to resolve.</param> /// <returns>This instance (can be used to chain calls together)</returns> public static EntityModelSchema Resolve(this EntityModelSchema schema) { var fixup = new ResolveReferencesFixup(); fixup.Fixup(schema); var enumDataTypeResolver = new EnumDataTypeResolver(schema); enumDataTypeResolver.ResolveEnumDataTypes(); return(schema); }
/// <summary> /// Performs a deep copy of the specified <see cref="EntityModelSchema"/>. /// </summary> /// <param name="schema">The <see cref="EntityModelSchema"/> to deep copy.</param> /// <returns>A deep copy of the <see cref="EntityModelSchema"/>.</returns> public static EntityModelSchema Clone(this EntityModelSchema schema) { ExceptionUtilities.CheckArgumentNotNull(schema, "schema"); var model = new EntityModelSchema(); CopyAnnotations(model, schema.Annotations); foreach (var association in schema.Associations) { model.Add(association.Clone()); } foreach (var complexType in schema.ComplexTypes) { model.Add(complexType.Clone()); } foreach (var entityContainer in schema.EntityContainers) { model.Add(entityContainer.Clone()); } foreach (var entityType in schema.EntityTypes) { model.Add(entityType.Clone()); } foreach (var enumType in schema.EnumTypes) { model.Add(enumType.Clone()); } foreach (var function in schema.Functions) { model.Add(function.Clone()); } model.Resolve(); return(model); }
/// <summary> /// Finds all functions matching given namespace and name. /// </summary> /// <param name="schema">Schema to search.</param> /// <param name="functionNamespace">The function namespace.</param> /// <param name="functionName">The function name.</param> /// <returns>Functions that match given namespace and name.</returns> public static IEnumerable <Function> FindFunctions(this EntityModelSchema schema, string functionNamespace, string functionName) { ExceptionUtilities.CheckArgumentNotNull(schema, "schema"); return(schema.Functions.Where(f => f.NamespaceName == functionNamespace && f.Name == functionName)); }