Class which represents a single resource instance.
Uses a property bag to store properties of the resource.
Exemple #1
0
        /// <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);
            });
        }
Exemple #2
0
        /// <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);
            });
        }
Exemple #4
0
        /// <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;
 }
Exemple #8
0
        /// <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);
         }
     }
 }
Exemple #10
0
        /// <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);
        }
Exemple #11
0
        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;
        }
Exemple #12
0
        /// <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);
Exemple #16
0
        /// <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;
        }
Exemple #17
0
        /// <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));
        }
Exemple #18
0
 public abstract void UpdateResource(string resourceSetName, DSPResource resource);
 public abstract void UpdateResource(string resourceSetName, DSPResource resource);
 public override void RemoveResource(string resourceSetName, DSPResource resource)
 {
     this.GetResourceSetStorage(resourceSetName).Remove(resource);
 }
Exemple #21
0
 public override void RemoveResource(string resourceSetName, DSPResource resource)
 {
     this.GetResourceSetStorage(resourceSetName).Remove(resource);
 }
Exemple #22
0
 public override void UpdateResource(string resourceSetName, DSPResource resource)
 {
 }
 public override void RemoveResource(string resourceSetName, DSPResource resource)
 {
 }
 public override void UpdateResource(string resourceSetName, DSPResource resource)
 {
 }
Exemple #25
0
 public abstract void RemoveResource(string resourceSetName, DSPResource resource);
Exemple #26
0
        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;
        }
Exemple #27
0
 public override void RemoveResource(string resourceSetName, DSPResource resource)
 {
 }