/// <summary> /// Fills in the given type declaration based on the given metadata /// </summary> /// <param name="entityType">The entity type's metadata</param> /// <param name="entityTypeClass">The type declaration</param> protected override void DeclareEntityType(EntityType entityType, CodeTypeDeclaration entityTypeClass) { entityTypeClass.IsPartial = true; entityTypeClass.IsClass = true; if (entityType.IsAbstract) { entityTypeClass.SetAbstract(); } if (entityType.BaseType != null) { entityTypeClass.BaseTypes.Add(entityType.BaseType.FullName); } // Add public constructor for this type var constructor = entityTypeClass.AddConstructor(); // Declare all members that are declared foreach (MemberProperty memberProperty in entityType.Properties) { this.DeclareMemberProperty(memberProperty, entityTypeClass); this.DeclareOptionalPropertyInitializer(memberProperty, constructor); } // Declare all members that are declared foreach (NavigationProperty navigationProperty in entityType.NavigationProperties) { this.DeclareNavigationProperty(navigationProperty, entityTypeClass); this.DeclareOptionalPropertyInitializer(navigationProperty, constructor); } this.GenerateAttributes(entityType, entityTypeClass); }
/// <summary> /// Adds new <see cref="EntityType"/> to the model. /// </summary> /// <param name="entityType">Entity type to be added.</param> public void Add(EntityType entityType) { ExceptionUtilities.CheckArgumentNotNull(entityType, "entityType"); ExceptionUtilities.Assert(entityType.Model == null, "Entity type was already added to another model"); entityType.Model = this; this.entityTypesList.Add(entityType); }
/// <summary> /// Generates and adds stream related attributes and elements to the entity type /// </summary> /// <param name="entityType">The entity type's metadata</param> /// <param name="entityTypeClass">The entity types declaration</param> protected override void GenerateHasStreamEntityTypeCodeElements(EntityType entityType, CodeTypeDeclaration entityTypeClass) { ExceptionUtilities.Assert(entityType.HasStream(), "This method should not be called for entity types without stream."); ClientMediaEntryAnnotation clientMediaEntryAnnotation = entityType.Annotations.OfType<ClientMediaEntryAnnotation>().FirstOrDefault(); if (clientMediaEntryAnnotation != null) { // generate MediaEntry and MimeTypeProperty properties and attributes for V1 style stream support var attributeArguments1 = new CodeAttributeArgument[] { new CodeAttributeArgument(Code.Primitive(clientMediaEntryAnnotation.MediaEntryName)), }; var attributeArguments2 = new CodeAttributeArgument[] { new CodeAttributeArgument(Code.Primitive(clientMediaEntryAnnotation.MediaEntryName)), new CodeAttributeArgument(Code.Primitive(clientMediaEntryAnnotation.MimeTypePropertyName)) }; entityTypeClass.AddCustomAttribute(Code.TypeRef("MediaEntry"), attributeArguments1); entityTypeClass.AddCustomAttribute(Code.TypeRef("MimeTypeProperty"), attributeArguments2); entityTypeClass.AddAutoImplementedProperty(Code.TypeRef<byte[]>(), clientMediaEntryAnnotation.MediaEntryName); entityTypeClass.AddAutoImplementedProperty(Code.TypeRef<string>(), clientMediaEntryAnnotation.MimeTypePropertyName); } else { // No ClientMediaEntryAnnotation is found, generate HasStream atttribute for V2 and up stream support entityTypeClass.AddCustomAttribute(Code.TypeRef("HasStream")); } }
/// <summary> /// Generates the conventional stream edit link for the given entity: http://serviceRoot/SetName(keyValues)/$value /// </summary> /// <param name="entitySet">The entity set of the entity</param> /// <param name="entityType">The type of the entity</param> /// <param name="keyValues">They values of the entity's key</param> /// <returns>The convention-based stream edit link</returns> public string GenerateDefaultStreamEditLink(EntitySet entitySet, EntityType entityType, IEnumerable<NamedValue> keyValues) { // null checks performed by this helper var uri = this.GenerateEntityEditLinkUri(entitySet, entityType, keyValues); uri.Segments.Add(SystemSegment.Value); return this.UriToStringConverter.ConvertToString(uri); }
private void RemoveObjectLayerOnlyNavigationProperties(EntityType entityType) { for (int i = entityType.NavigationProperties.Count - 1; i >= 0; i--) { if (entityType.NavigationProperties[i].Annotations.OfType<ObjectLayerOnlyAnnotation>().Any()) { entityType.NavigationProperties.RemoveAt(i); } } }
/// <summary> /// Gets the properties values for all scalar and complex properties in the form of <see cref="NamedValue"/>. /// </summary> /// <param name="objectServices">The object services.</param> /// <param name="entity">The entity.</param> /// <param name="entityType">Type of the entity.</param> /// <returns>The properties values.</returns> public static IList<NamedValue> GetPropertiesValues(this IEntityModelObjectServices objectServices, object entity, EntityType entityType) { ExceptionUtilities.CheckArgumentNotNull(objectServices, "objectServices"); ExceptionUtilities.CheckArgumentNotNull(entity, "entity"); ExceptionUtilities.CheckArgumentNotNull(entityType, "entityType"); List<NamedValue> result = new List<NamedValue>(); CachePropertiesValues(result, string.Empty, entityType.FullName, entityType.AllProperties, entity, objectServices); return result; }
/// <summary> /// Fills in the given type declaration based on the given metadata and implements INotifyPropertyChanged on the type /// </summary> /// <param name="entityType">The entity type's metadata</param> /// <param name="entityTypeClass">The type declaration</param> protected override void DeclareEntityType(EntityType entityType, CodeTypeDeclaration entityTypeClass) { base.DeclareEntityType(entityType, entityTypeClass); // if an entity type is a derived type, the base type should have implemented INotifyPropertyChanged if (entityType.BaseType == null) { this.ImplementINotifyPropertyChanged(entityTypeClass); } }
private int GetNumberOfInheritanceLevel(EntityModelSchema model, EntityType entityType) { var children = model.EntityTypes.Where(e => e.BaseType == entityType); if (children.Any()) { return 1 + children.Max(e => this.GetNumberOfInheritanceLevel(model, e)); } return 0; }
/// <summary> /// Improve the model if goals not yet met /// </summary> /// <param name="model">model to improve</param> public override void Improve(EntityModelSchema model) { var roots = this.GetInheritanceRoots(model); int numberOfRootsToAdd = this.MinNumberOfInheritanceRoots - roots.Count(); for (int i = 0; i < numberOfRootsToAdd; i++) { var root = new EntityType(); model.Add(root); model.Add(new EntityType() { BaseType = root }); } }
/// <summary> /// Improve the model if goals not yet met /// </summary> /// <param name="model">model to improve</param> public override void Improve(EntityModelSchema model) { var baseType = new EntityType(); model.Add(baseType); for (int i = 0; i < this.MinNumberOfInheritanceLevels; i++) { var derivedType = new EntityType() { BaseType = baseType }; model.Add(derivedType); baseType = derivedType; } }
/// <summary> /// Visits an entity /// </summary> /// <param name="entity">entity to visit</param> protected virtual void VisitEntityType(EntityType entity) { this.VisitAnnotatedItem(entity); foreach (var property in entity.Properties) { this.VisitMemberProperty(property); } foreach (var navigationProperty in entity.NavigationProperties) { this.VisitNavigationProperty(navigationProperty); } }
/// <summary> /// Considers the candidate for this relationship. /// </summary> /// <param name="entitySet">The entity set.</param> /// <param name="entityType">Type of the entity.</param> /// <param name="key">The entity data key of the candidate.</param> public void ConsiderCandidate(EntitySet entitySet, EntityType entityType, EntityDataKey key) { foreach (RelationshipGroupEnd end in this.ends.Where(e => e.EntitySet == entitySet && entityType.IsKindOf(e.EntityType))) { CapacityRange capacityRange = end.CapacitySelector(); if (capacityRange != CapacityRange.Zero) { this.RemoveCandidatesOnTargetBasedOnTreshhold(end); RelationshipCandidate candidate = new RelationshipCandidate(end, key, capacityRange); end.Candidates.Add(candidate); } } }
/// <summary> /// Improve the model if goals not yet met /// </summary> /// <param name="model">model to improve</param> public override void Improve(EntityModelSchema model) { var baseTypes = model.EntityTypes.Where(e => model.EntityTypes.Any(d => d.BaseType == e)).ToList(); foreach (var baseType in baseTypes) { int numberOfSiblingsToAdd = this.MinNumberOfInheritanceSiblings - model.EntityTypes.Count(d => d.BaseType == baseType); for (int i = 0; i < numberOfSiblingsToAdd; i++) { var derivedType = new EntityType() { BaseType = baseType }; model.Add(derivedType); } } }
/// <summary> /// Creates a default instance of a CLR object which represents the specified <paramref name="entityType"/> and <paramref name="entitySet"/>. /// </summary> /// <param name="objectServices">The object services.</param> /// <param name="entitySet">The <see cref="EntitySet"/> in which the <paramref name="entityType"/> resides.</param> /// <param name="entityType">The <see cref="EntityType"/> from which to create a CLR object.</param> /// <returns>A CLR object that maps to the <paramref name="entityType"/>.</returns> public static object CreateData(this IEntityModelObjectServices objectServices, EntitySet entitySet, EntityType entityType) { ExceptionUtilities.CheckArgumentNotNull(objectServices, "objectServices"); ExceptionUtilities.CheckArgumentNotNull(entitySet, "entitySet"); ExceptionUtilities.CheckArgumentNotNull(entityType, "entityType"); if (entityType.IsAbstract) { throw new TaupoArgumentException("Cannot create data for abstract entity type."); } var generator = objectServices.GetEntitySetObjectGenerator(entityType.FullName, entitySet.ContainerQualifiedName); var entity = generator.GenerateData().Data; return entity; }
/// <summary> /// Checks for a name collision between an action's name and a property's name /// </summary> /// <param name="function">The function to check for name property collision</param> /// <param name="bindingEntityDataType">The bindingEntityDataType is the entity to check against</param> /// <param name="actualInstanceEntityType">the entity type of the instance of the entity</param> /// <returns>a string representing the entity container's name</returns> public string BuildExpectedContainerName(Function function, EntityDataType bindingEntityDataType, EntityType actualInstanceEntityType) { string containerName = string.Empty; // check for open entity type on the function definition or on the actual entity itself if (bindingEntityDataType.Definition.IsOpen || actualInstanceEntityType.IsOpen) { containerName = string.Concat(function.Model.GetDefaultEntityContainer().Name, "."); } var foundNameCollision = bindingEntityDataType.Definition.AllProperties.Where(a => a.Name.Equals(function.Name)).FirstOrDefault(); if (foundNameCollision != null && !bindingEntityDataType.Definition.IsOpen) { containerName = string.Concat(function.Model.GetDefaultEntityContainer().Name, "."); } return containerName; }
/// <summary> /// Constructs an entity with the given property values /// </summary> /// <param name="entityType">The metadata for the entity type</param> /// <param name="namedValues">The property values. Keys are expected to be '.' delimited property paths.</param> /// <returns>An entity instance with the given values</returns> public EntityInstance EntityInstance(EntityType entityType, IEnumerable<NamedValue> namedValues) { ExceptionUtilities.CheckArgumentNotNull(entityType, "entityType"); EntityInstance instance = new EntityInstance(entityType.FullName, namedValues == null); if (entityType.GetBaseTypesAndSelf().Any(t => t.HasStream())) { instance.AsMediaLinkEntry(); } if (namedValues != null) { this.PopulatePropertiesFromPaths(instance, entityType.AllProperties, null, namedValues); // TODO: populate navigation properties } return instance; }
/// <summary> /// Builds an entity instance of the given type out of the given anonymous object /// </summary> /// <param name="entityType">The metadata type information for the entity</param> /// <param name="anonymous">The data as an anonymous type</param> /// <returns>An entity instance with the given values</returns> public EntityInstance EntityInstance(EntityType entityType, object anonymous) { ExceptionUtilities.CheckArgumentNotNull(entityType, "entityType"); EntityInstance instance = new EntityInstance(entityType.FullName, anonymous == null); if (entityType.GetBaseTypesAndSelf().Any(t => t.HasStream())) { instance.AsMediaLinkEntry(); } // TODO: id? if (anonymous != null) { this.PopulatePropertiesFromObject(instance, entityType.AllProperties, anonymous); // TODO: populate navigation properties } return instance; }
/// <summary> /// Constructs a key expression segment with the given values /// </summary> /// <param name="type">The type for the key</param> /// <param name="values">The values for the key</param> /// <returns>A key expression segment</returns> public static ODataUriSegment Key(EntityType type, IEnumerable<NamedValue> values) { ExceptionUtilities.CheckArgumentNotNull(type, "type"); ExceptionUtilities.CheckCollectionNotEmpty(values, "values"); // intentionally avoiding using a linq-to-objects query as it introduces a compiler-generated class that shows up in the dependency layering output List<KeyValuePair<MemberProperty, object>> pairs = new List<KeyValuePair<MemberProperty, object>>(); Dictionary<string, MemberProperty> keyProperties = new Dictionary<string, MemberProperty>(); foreach (var keyProperty in type.AllKeyProperties) { keyProperties[keyProperty.Name] = keyProperty; } foreach (var pair in values) { MemberProperty keyProperty; ExceptionUtilities.Assert(keyProperties.TryGetValue(pair.Name, out keyProperty), "Could not find key property '" + pair.Name + "'"); pairs.Add(new KeyValuePair<MemberProperty, object>(keyProperty, pair.Value)); } ExceptionUtilities.Assert(pairs.Count == values.Count(), "Number of pairs does not match input"); return new KeyExpressionSegment(pairs); }
internal static bool TryGetExpectedType(ODataRequest request, out EntityType entityType) { EntitySet entitySet; if (request.Uri.TryGetExpectedEntitySet(out entitySet)) { var possibleTypes = entitySet.Container.Model.EntityTypes.Where(t => t.IsKindOf(entitySet.EntityType)).ToList(); if (possibleTypes.Count == 1) { entityType = possibleTypes[0]; return true; } string typeName = null; if (entitySet.EntityType.HasStream()) { typeName = request.GetHeaderValueIfExists(HttpHeaders.MediaLinkEntryEntityTypeHint); } else if (request.Body != null && request.Body.RootElement.ElementType == ODataPayloadElementType.EntityInstance) { typeName = ((EntityInstance)request.Body.RootElement).FullTypeName; } if (typeName != null) { entityType = possibleTypes.SingleOrDefault(t => t.FullName == typeName); return entityType != null; } } entityType = null; return false; }
/// <summary> /// Initializes a new instance of the EntitySetDataRowWithStreams class /// </summary> /// <param name="parent">The parent of the row</param> /// <param name="entityType">The entity type of the row</param> public EntitySetDataRowWithStreams(EntitySetData parent, EntityType entityType) : base(parent, entityType) { this.Streams = new List<StreamData>(); }
/// <summary> /// Gets the CLR instance type for the specified entity type. /// </summary> /// <param name="entity">The entity type to get the instance type for.</param> /// <param name="canReflectOnInstanceType">true if reflection over the instance type is allowed; otherwise false.</param> /// <returns>The CLR instance type to use.</returns> protected override Type GetEntityInstanceType(EntityType entity, out bool canReflectOnInstanceType) { canReflectOnInstanceType = false; return typeof(DSPResource); }
private EntitySetDataRow PopulateEntitySetRow(EntityContainerData data, EntitySet entitySet, EntityType entityType, IEnumerable<NamedValue> entityData) { EntitySetDataRow row = data[entitySet].AddNewRowOfType(entityType); foreach (NamedValue namedValue in entityData) { row.SetValue(namedValue.Name, namedValue.Value); } this.entitySetAndTypeSelector.IncrementCount(entitySet, entityType); return row; }
private EntitySetDataRow PopulateNewEntitySetRow(EntityContainerData data, EntitySet entitySet, EntityType entityType) { var entityData = this.StructuralDataServices.GetStructuralGenerator(entityType.FullName, this.EntityContainer.Name + "." + entitySet.Name).GenerateData(); return this.PopulateEntitySetRow(data, entitySet, entityType, entityData); }
private bool GetNextEntitySetAndTypeToCreate(out EntitySet entitySet, out EntityType entityType) { if (this.entitiesToCreateInNextBatch.Count > 0) { var entitySetAndType = this.Random.ChooseFrom(this.entitiesToCreateInNextBatch); entitySet = entitySetAndType.Key; entityType = entitySetAndType.Value; return true; } else { return this.entitySetAndTypeSelector.TryGetNextEntitySetAndTypeToCreate(out entitySet, out entityType); } }
/// <summary> /// Sets the minimum number of entities to be created for the specified entity set and type. /// </summary> /// <param name="entitySet">The entity set.</param> /// <param name="entityType">The entity type.</param> /// <param name="count">The minimum number of entities to create.</param> public void SetMinimumNumberOfEntities(EntitySet entitySet, EntityType entityType, int count) { ExceptionUtilities.CheckArgumentNotNull(entitySet, "entitySet"); ExceptionUtilities.CheckArgumentNotNull(entityType, "entityType"); this.SetMinimumNumberOfEntities(entitySet.Name, entityType.Name, count); }
/// <summary> /// Adds seed data to the <see cref="EntityContainerData"/> created by this instance by /// calling <see cref="TryPopulateNextData"/>. /// </summary> /// <param name="entitySet">The <see cref="EntitySet"/> to which the new seed instance belongs.</param> /// <param name="entityType">The <see cref="EntityType"/> of the new seed instance.</param> /// <param name="entityData">A collection of <see cref="NamedValue"/>s that describe the structural data of the instance.</param> /// <returns>The <see cref="EntityDataKey"/> that describes the seed instance.</returns> public EntityDataKey Seed(EntitySet entitySet, EntityType entityType, IEnumerable<NamedValue> entityData) { this.CreateEntitySetAndTypeSelectorIfNull(); this.CreateRelationshipSelectorsIfNull(); if (this.seedData == null) { this.seedData = new EntityContainerData(this.entityContainer); } var seedRow = this.PopulateEntitySetRow(this.seedData, entitySet, entityType, entityData); this.ConsiderCandidateForRelationships(seedRow); return seedRow.Key; }
/// <summary> /// Converts a potential HasStream annotation to the corresponding test annotation on the <paramref name="entityType"/>. /// </summary> /// <param name="entityType">EntityType to convert the annotations on.</param> private void ConvertHasStreamAnnotation(EntityType entityType) { ExceptionUtilities.CheckArgumentNotNull(entityType, "entityType"); var hasStreamAnnotation = entityType.Annotations.OfType<AttributeAnnotation>() .Where(ann => ann.Content != null && ann.Content.Name.LocalName == "HasStream").SingleOrDefault(); if (hasStreamAnnotation != null) { bool hasStreamValue = bool.Parse(hasStreamAnnotation.Content.Value); if (hasStreamValue) { entityType.Add(new HasStreamAnnotation()); } } }
/// <summary> /// Visit entity type to convert annotations /// </summary> /// <param name="entity">Entity type to visit</param> protected override void VisitEntityType(EntityType entity) { this.ConvertHasStreamAnnotation(entity); base.VisitEntityType(entity); }
private void CompareEntityTypes(EntityType expectedEntityType, EntityType actualEntityType) { string actualBaseTypeName = null; string expectedBaseTypeName = null; if (expectedEntityType.BaseType != null) { expectedBaseTypeName = expectedEntityType.BaseType.Name; } if (actualEntityType.BaseType != null) { actualBaseTypeName = actualEntityType.BaseType.Name; } this.WriteErrorIfFalse(expectedBaseTypeName == actualBaseTypeName, "EntityType BaseType property does not match Expected '{0}' Actual '{1}'", expectedBaseTypeName, actualBaseTypeName); this.CompareMemberProperties(expectedEntityType, expectedEntityType.Properties, actualEntityType.Properties); foreach (NavigationProperty navigationProperty in expectedEntityType.NavigationProperties) { List<NavigationProperty> actualNavProps = actualEntityType.NavigationProperties.Where(p => p.Name == navigationProperty.Name).ToList(); if (!this.WriteErrorIfFalse(actualNavProps.Count == 1, "Cannot find NavProp '{0}'", navigationProperty.Name)) { NavigationProperty actualNavigationProperty = actualNavProps.Single(); this.CompareNavigationProperty(navigationProperty, actualNavigationProperty); } } }
/// <summary> /// Generates 'EntityType' XElement based on <see cref="EntityType"/>. /// </summary> /// <param name="xmlNamespace">XML namespace to use</param> /// <param name="entityType">Entity type</param> /// <returns><see cref="XElement"/> representing EntityType.</returns> protected override XElement GenerateEntityType(XNamespace xmlNamespace, EntityType entityType) { var element = base.GenerateEntityType(xmlNamespace, entityType); TypeAccessModifierAnnotation annotation = entityType.Annotations.OfType<TypeAccessModifierAnnotation>().SingleOrDefault(); element.Add(GenerateTypeAccessModifier(annotation)); return element; }