/// <summary> /// Sets the value of the given property on the target object /// </summary> /// <param name="targetResource">target object which defines the property</param> /// <param name="propertyName">name of the property whose value needs to be updated</param> /// <param name="propertyValue">value of the property</param> /// <remarks>This method should pend a change which will set a resource property with name <paramref name="propertyName"/> /// to value specified by <paramref name="propertyValue"/> on the resource specified by the resource "handle" <paramref name="targetResource"/>. /// All changes made by this method should be creates as pending until SaveChanges is called which will commit them (or if it's not called and ClearChanges /// is called instead they should be discarded).</remarks> public void SetValue(object targetResource, string propertyName, object propertyValue) { DSPResource dspTargetResource = ValidateDSPResource(targetResource); // Add a pending change to modify the value of the property this.pendingChanges.Add(() => { dspTargetResource.SetValue(propertyName, propertyValue); }); }
/// <summary>Validates that the <paramref name="resource"/> is a <see cref="DSPResource"/>.</summary> /// <param name="resource">The resource instance to validate.</param> /// <returns>The resource instance casted to <see cref="DSPResource"/>.</returns> public static DSPResource ValidateDSPResource(object resource) { DSPResource dspResource = resource as DSPResource; if (resource != null && dspResource == null) { throw new ArgumentException("The specified resource is not a DSPResource. That is not supported by this provider."); } return(dspResource); }
/// <summary> /// Delete the given resource /// </summary> /// <param name="targetResource">resource that needs to be deleted</param> /// <remarks>This method gets a "handle" to a resource in the <paramref name="targetResource"/> and should pend a change which /// deletes that resource. /// That includes removing the resource from its resource set and freeing up all the resources associated with that resource. /// Note that this method is not called for complex type instances, only entity resurces are deleted in this way. Complex type instances /// should be deleted when the entity type which points to them is deleted. /// All changes made by this method should be creates as pending until SaveChanges is called which will commit them (or if it's not called and ClearChanges /// is called instead they should be discarded).</remarks> public virtual void DeleteResource(object targetResource) { DSPResource dspTargetResource = ValidateDSPResource(targetResource); ResourceSet resourceSet = dspTargetResource.ResourceType.GetAnnotation().ResourceSet; // Add a pending change to remove the resource from the resource set this.pendingChanges.Add(() => { this.dataContext.RemoveResource(resourceSet.Name, dspTargetResource); }); }
/// <summary> /// Delete the given resource /// </summary> /// <param name="targetResource">resource that needs to be deleted</param> /// <remarks>This method gets a "handle" to a resource in the <paramref name="targetResource"/> and should pend a change which /// deletes that resource. /// That includes removing the resource from its resource set and freeing up all the resources associated with that resource. /// Note that this method is not called for complex type instances, only entity resurces are deleted in this way. Complex type instances /// should be deleted when the entity type which points to them is deleted. /// All changes made by this method should be creates as pending until SaveChanges is called which will commit them (or if it's not called and ClearChanges /// is called instead they should be discarded).</remarks> public void DeleteResource(object targetResource) { DSPResource dspTargetResource = ValidateDSPResource(targetResource); ResourceSet resourceSet = dspTargetResource.ResourceType.GetAnnotation().ResourceSet; IList <DSPResource> resourceSetList = this.dataContext.GetResourceSetEntities(resourceSet.Name); // Add a pending change to remove the resource from the resource set this.pendingChanges.Add(() => { resourceSetList.Remove(dspTargetResource); }); }
/// <summary>Returns a resource type for the specified resource.</summary> /// <param name="target">The target resource for which to determine its type.</param> /// <returns>The <see cref="ResourceType"/> of the specified resource.</returns> /// <remarks>The method should throw if the resource is not recognized. If it returns null the data service will throw instead.</remarks> public ResourceType GetResourceType(object target) { DSPResource entity = target as DSPResource; if (entity != null) { return(entity.ResourceType); } else { throw new NotSupportedException("Unrecognized resource type."); } }
/// <summary>Gets a value of a declared property for a resource.</summary> /// <param name="target">The target resource to get a value of the property from.</param> /// <param name="resourceProperty">The name of the property to get.</param> /// <returns>The value of the property.</returns> /// <remarks>The returned value's type should match the type declared in the resource's resource type.</remarks> public object GetPropertyValue(object target, ResourceProperty resourceProperty) { DSPResource entity = target as DSPResource; if (entity != null) { return(entity.GetValue(resourceProperty.Name)); } else { throw new NotSupportedException("Unrecognized resource type."); } }
public static BsonDocument CreateBSonDocument(DSPResource resource, MongoMetadata mongoMetadata, string resourceName) { var document = new BsonDocument(); var resourceSet = mongoMetadata.ResolveResourceSet(resourceName); if (resourceSet != null) { foreach (var property in resourceSet.ResourceType.Properties) { var propertyValue = resource.GetValue(property.Name); if (propertyValue != null) { document.Set(property.Name, BsonValue.Create(propertyValue)); } } } return document; }
/// <summary> /// Resets the value of the given resource to its default value /// </summary> /// <param name="resource">resource whose value needs to be reset</param> /// <returns>same resource with its value reset</returns> /// <remarks>This method should reset resource properties to their default values. /// The resource is specfied by its resource "handle" by the <paramref name="resource"/>. /// The method can choose to modify the existing resource or create a new one and it should return a resource "handle" /// to the resource which has its properties with default values. If it chooses to return a new resource it must also /// replace that old resource with the new one in its resource set and all the references which may point to it. /// The returned resource must have the same identity as the one on the input. That means all its key properties must have the same value. /// All changes made by this method should be creates as pending until SaveChanges is called which will commit them (or if it's not called and ClearChanges /// is called instead they should be discarded).</remarks> public object ResetResource(object resource) { DSPResource dspResource = ValidateDSPResource(resource); this.pendingChanges.Add(() => { foreach (var resourceProperty in dspResource.ResourceType.Properties) { // We must only reset values of non-key properties, the key properties must be persited (to maintain the identity of the resource instance) if ((resourceProperty.Kind & ResourcePropertyKind.Key) != ResourcePropertyKind.Key) { dspResource.SetValue(resourceProperty.Name, null); } } }); return(resource); }
private static void AssignNullCollections(DSPResource resource, ResourceType resourceType) { foreach (var resourceProperty in resourceType.Properties) { var propertyValue = resource.GetValue(resourceProperty.Name); if (resourceProperty.Kind == ResourcePropertyKind.Collection) { if (propertyValue == null) { resource.SetValue(resourceProperty.Name, new object[0]); } } else if (propertyValue is DSPResource) { AssignNullCollections(propertyValue as DSPResource, resourceProperty.ResourceType); } } }
/// <summary> /// Creates the resource of the given type and belonging to the given container /// </summary> /// <param name="containerName">container name to which the resource needs to be added</param> /// <param name="fullTypeName">full type name i.e. Namespace qualified type name of the resource</param> /// <returns>object representing a resource of given type and belonging to the given container</returns> /// <remarks>The method should create a new instance of the resource type specified by the <paramref name="fullTypeName"/> /// and add it to the resource set specified by the <paramref name="containerName"/>. /// The method should then return the "handle" to the resource just created. /// All properties of the new resource should have their default values. /// This method is called in two slightly different cases: /// - entity resource creation - in this case the <paramref name="containerName"/> specifies the name of the resource set /// the newly created entity should be added to and the <paramref name="fullTypeName"/> is the FullName of the resource type representing /// entity type. The method should create new instance of the type and add it to the resource set. /// - complex resource creation - in this case the <paramref name="containerName"/> is null and the <paramref name="fullTypeName"/> /// specified the FullName of the resource type representing a complex type. The method should just create new instance of the type /// and return it. Later the <see cref="SetValue"/> will be called to set the complex type instance returned as a value of some /// complex property. /// All changes made by this method should be creates as pending until SaveChanges is called which will commit them (or if it's not called and ClearChanges /// is called instead they should be discarded).</remarks> public object CreateResource(string containerName, string fullTypeName) { ResourceType resourceType; if (!this.metadata.TryResolveResourceType(fullTypeName, out resourceType)) { throw new ArgumentException("Unknown resource type '" + fullTypeName + "'."); } // Create new instance of the DSPResource (this will create empty property bag, which is the same as all properties having default values) DSPResource newResource = new DSPResource(resourceType); if (containerName != null) { // We're creating an entity and should add it to the resource set // This check here is just for documentation, the method should never be called with non-entity type in this case. if (resourceType.ResourceTypeKind != ResourceTypeKind.EntityType) { throw new ArgumentException("The specified resource type '" + fullTypeName + "' is not an entity type, but resource set was specified."); } IList <DSPResource> resourceSetList = this.dataContext.GetResourceSetEntities(containerName); // And register pending change to add the resource to the resource set list this.pendingChanges.Add(() => { resourceSetList.Add(newResource); }); } else { // We're creating a complex type instance, so no additional operation is needed. // This check here is just for documentation the method should never be called with non-complex type in this case. if (resourceType.ResourceTypeKind != ResourceTypeKind.ComplexType) { throw new ArgumentException("The specified resource type '" + fullTypeName + "' is not a complex type."); } } // The method should return the resource "handle", we don't have handles so we return the resource itself directly. return(newResource); }
public static DSPResource CreateDSPResource(BsonDocument document, MongoMetadata mongoMetadata, string resourceName, string ownerPrefix = null) { var resourceType = mongoMetadata.ResolveResourceType(resourceName, ownerPrefix); if (resourceType == null) throw new ArgumentException(string.Format("Unable to resolve resource type {0}", resourceName), "resourceName"); var resource = new DSPResource(resourceType); foreach (var element in document.Elements) { var resourceProperty = mongoMetadata.ResolveResourceProperty(resourceType, element); if (resourceProperty == null) continue; object propertyValue = ConvertBsonValue(element.Value, resourceType, resourceProperty, resourceProperty.Name, mongoMetadata); resource.SetValue(resourceProperty.Name, propertyValue); } AssignNullCollections(resource, resourceType); return resource; }
/// <summary> /// Adds the given value to the collection /// </summary> /// <param name="targetResource">target object which defines the property</param> /// <param name="propertyName">name of the property whose value needs to be updated</param> /// <param name="resourceToBeAdded">value of the property which needs to be added</param> /// <remarks>Adds resource instance <paramref name="resourceToBeAdded"/> into a resource reference set /// <paramref name="propertyName"/> on resource <paramref name="targetResource"/>. /// Both resources, that is <paramref name="targetResource"/> and <paramref name="resourceToBeAdded"/>, are specified /// in the parameters as the resource "handle". /// All changes made by this method should be creates as pending until SaveChanges is called which will commit them (or if it's not called and ClearChanges /// is called instead they should be discarded).</remarks> public void AddReferenceToCollection(object targetResource, string propertyName, object resourceToBeAdded) { // We don't use resource "handles" so both resources passed in as parameters are the real resource instances. DSPResource dspTargetResource = ValidateDSPResource(targetResource); DSPResource dspResourceToBeAdded = ValidateDSPResource(resourceToBeAdded); // All resource set reference properties must be of type IList<DSPResource> (assumption of this provider) // Note that we don't support bi-directional relationships so we only handle the one resource set reference property in isolation. IList <DSPResource> list = dspTargetResource.GetValue(propertyName) as IList <DSPResource>; if (list == null) { throw new ArgumentException("The value of the property '" + propertyName + "' does not implement IList<DSPResource>, which is a requirement for resource set reference property."); } this.pendingChanges.Add(() => { list.Add(dspResourceToBeAdded); }); }
private DSPResource CreateDSPResource(ResourceType resourceType, BsonDocument bsonDocument) { var resource = new DSPResource(resourceType); foreach (var element in bsonDocument.Elements) { if (element.Name == "_id") { resource.SetValue("ID", element.Value.ToString()); this.resourceMap.Add(element.Value.AsObjectId, resource); } else if (element.Value.GetType() == typeof(BsonDocument)) { this.resourceReferences.Add(new Tuple<ObjectId, string, ObjectId>( bsonDocument["_id"].AsObjectId, element.Name, element.Value.AsBsonDocument["_id"].AsObjectId)); } else if (element.Value.GetType() == typeof(BsonArray)) { var bsonArray = element.Value.AsBsonArray; if (bsonArray != null && bsonArray.Count > 0) { var tuple = new Tuple<ObjectId, string, List<ObjectId>>( bsonDocument["_id"].AsObjectId, element.Name, new List<ObjectId>()); resourceSetReferences.Add(tuple); foreach (var item in bsonArray) { tuple.Item3.Add(item.AsBsonDocument["_id"].AsObjectId); } } } else if (element.Value.RawValue != null) { resource.SetValue(element.Name, element.Value.RawValue); } } return resource; }
public ResourceChange(string collectionName, DSPResource resource, Action<MongoContext, ResourceChange> action) { this.CollectionName = collectionName; this.Resource = resource; this.Action = action; this.ModifiedProperties = new Dictionary<string, object>(); }
public abstract void RemoveResource(string resourceSetName, DSPResource resource);
/// <summary> /// Creates the resource of the given type and belonging to the given container /// </summary> /// <param name="containerName">container name to which the resource needs to be added</param> /// <param name="fullTypeName">full type name i.e. Namespace qualified type name of the resource</param> /// <returns>object representing a resource of given type and belonging to the given container</returns> /// <remarks>The method should create a new instance of the resource type specified by the <paramref name="fullTypeName"/> /// and add it to the resource set specified by the <paramref name="containerName"/>. /// The method should then return the "handle" to the resource just created. /// All properties of the new resource should have their default values. /// This method is called in two slightly different cases: /// - entity resource creation - in this case the <paramref name="containerName"/> specifies the name of the resource set /// the newly created entity should be added to and the <paramref name="fullTypeName"/> is the FullName of the resource type representing /// entity type. The method should create new instance of the type and add it to the resource set. /// - complex resource creation - in this case the <paramref name="containerName"/> is null and the <paramref name="fullTypeName"/> /// specified the FullName of the resource type representing a complex type. The method should just create new instance of the type /// and return it. Later the <see cref="SetValue"/> will be called to set the complex type instance returned as a value of some /// complex property. /// All changes made by this method should be creates as pending until SaveChanges is called which will commit them (or if it's not called and ClearChanges /// is called instead they should be discarded).</remarks> public virtual object CreateResource(string containerName, string fullTypeName) { ResourceType resourceType; if (!this.metadata.TryResolveResourceType(fullTypeName, out resourceType)) { throw new ArgumentException("Unknown resource type '" + fullTypeName + "'."); } // Create new instance of the DSPResource (this will create empty property bag, which is the same as all properties having default values) DSPResource newResource = new DSPResource(resourceType); if (containerName != null) { // We're creating an entity and should add it to the resource set // This check here is just for documentation, the method should never be called with non-entity type in this case. if (resourceType.ResourceTypeKind != ResourceTypeKind.EntityType) { throw new ArgumentException("The specified resource type '" + fullTypeName + "' is not an entity type, but resource set was specified."); } // And register pending change to add the resource to the resource set list this.pendingChanges.Add(() => { this.dataContext.AddResource(containerName, newResource); }); } else { // We're creating a complex type instance, so no additional operation is needed. // This check here is just for documentation the method should never be called with non-complex type in this case. if (resourceType.ResourceTypeKind != ResourceTypeKind.ComplexType) { throw new ArgumentException("The specified resource type '" + fullTypeName + "' is not a complex type."); } } // The method should return the resource "handle", we don't have handles so we return the resource itself directly. return newResource; }
/// <summary> /// Gets the value of the given property on the target object /// </summary> /// <param name="targetResource">target object which defines the property</param> /// <param name="propertyName">name of the property whose value needs to be updated</param> /// <returns>the value of the property for the given target resource</returns> /// <remarks>The method gets a resource "handle" in the <paramref name="targetResource"/> and the name of a resource property /// defined on it and should return the value of that property.</remarks> public object GetValue(object targetResource, string propertyName) { DSPResource dspTargetResource = ValidateDSPResource(targetResource); return(dspTargetResource.GetValue(propertyName)); }
public abstract void UpdateResource(string resourceSetName, DSPResource resource);
public override void RemoveResource(string resourceSetName, DSPResource resource) { this.GetResourceSetStorage(resourceSetName).Remove(resource); }
public override void UpdateResource(string resourceSetName, DSPResource resource) { }
public override void RemoveResource(string resourceSetName, DSPResource resource) { }
public static DSPResource CreateDSPResource(BsonDocument document, MongoMetadata mongoMetadata, string resourceName, string ownerPrefix = null) { var resourceType = mongoMetadata.ResolveResourceType(resourceName, ownerPrefix); if (resourceType == null) throw new ArgumentException(string.Format("Unable to resolve resource type {0}", resourceName), "resourceName"); var resource = new DSPResource(resourceType); foreach (var element in document.Elements) { var resourceProperty = mongoMetadata.ResolveResourceProperty(resourceType, element); if (resourceProperty == null) continue; string propertyName = null; object propertyValue = null; if (MongoMetadata.IsObjectId(element)) { propertyName = MongoMetadata.MappedObjectIdName; propertyValue = element.Value.RawValue.ToString(); } else if (element.Value.GetType() == typeof(BsonDocument)) { propertyName = element.Name; propertyValue = CreateDSPResource(element.Value.AsBsonDocument, mongoMetadata, element.Name, MongoMetadata.GetComplexTypePrefix(resourceType.Name)); } else if (element.Value.GetType() == typeof(BsonArray)) { var bsonArray = element.Value.AsBsonArray; if (bsonArray != null && bsonArray.Count > 0) { propertyName = element.Name; int nonNullItemCount = 0; for (int index = 0; index < bsonArray.Count; index++) { if (bsonArray[index] != BsonNull.Value) ++nonNullItemCount; } var valueArray = new DSPResource[nonNullItemCount]; int valueIndex = 0; for (int index = 0; index < bsonArray.Count; index++) { if (bsonArray[index] != BsonNull.Value) { valueArray[valueIndex++] = CreateDSPResource(bsonArray[index].AsBsonDocument, mongoMetadata, element.Name, MongoMetadata.GetCollectionTypePrefix(resourceType.Name)); } } propertyValue = valueArray; } } else { propertyName = element.Name; if (element.Value.RawValue != null) { switch (element.Value.BsonType) { case BsonType.DateTime: propertyValue = UnixEpoch + TimeSpan.FromMilliseconds(element.Value.AsBsonDateTime.MillisecondsSinceEpoch); break; default: propertyValue = element.Value.RawValue; break; } } else { switch (element.Value.BsonType) { case BsonType.Binary: propertyValue = element.Value.AsBsonBinaryData.Bytes; break; default: propertyValue = element.Value.RawValue; break; } } } if (propertyValue != null && element.Value.GetType() != typeof(BsonArray)) { propertyValue = Convert.ChangeType(propertyValue, resourceProperty.ResourceType.InstanceType); } resource.SetValue(propertyName, propertyValue); } return resource; }