/// <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());
     }
 }
Beispiel #19
0
        /// <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));
 }