Exemplo n.º 1
0
        /// <summary>
        /// Given a source of resources, gets the implicitly affected resources from the database and calls the BeforeImplicitUpdateRelationship hook.
        /// </summary>
        private void FireForAffectedImplicits(Type resourceTypeToInclude, IDictionary <RelationshipAttribute, IEnumerable> implicitsTarget,
                                              ResourcePipeline pipeline, IEnumerable existingImplicitResources = null)
        {
            IResourceHookContainer container =
                _containerProvider.GetResourceHookContainer(resourceTypeToInclude, ResourceHook.BeforeImplicitUpdateRelationship);

            if (container == null)
            {
                return;
            }

            IDictionary <RelationshipAttribute, IEnumerable> implicitAffected =
                _containerProvider.LoadImplicitlyAffected(implicitsTarget, existingImplicitResources);

            if (!implicitAffected.Any())
            {
                return;
            }

            Dictionary <RelationshipAttribute, IEnumerable> inverse = new Dictionary <RelationshipAttribute, IEnumerable>();

            foreach (KeyValuePair <RelationshipAttribute, IEnumerable> pair in implicitAffected)
            {
                var inverseRelationship = _resourceGraph.GetInverseRelationship(pair.Key);
                if (inverseRelationship != null)
                {
                    inverse.Add(inverseRelationship, pair.Value);
                }
            }

            IRelationshipsDictionary resourcesByRelationship = CreateRelationshipHelper(resourceTypeToInclude, inverse);

            CallHook(container, ResourceHook.BeforeImplicitUpdateRelationship, ArrayFactory.Create <object>(resourcesByRelationship, pipeline));
        }
Exemplo n.º 2
0
        /// <summary>
        /// Fires the AfterUpdateRelationship hook
        /// </summary>
        private void FireAfterUpdateRelationship(IResourceHookContainer container, IResourceNode node, ResourcePipeline pipeline)
        {
            IDictionary <RelationshipAttribute, IEnumerable> currentResourcesGrouped = node.RelationshipsFromPreviousLayer.GetRightResources();

            // the relationships attributes in currentResourcesGrouped will be pointing from a
            // resource in the previous layer to a resource in the current (nested) layer.
            // For the nested hook we need to replace these attributes with their inverse.
            // See the FireNestedBeforeUpdateHooks method for a more detailed example.
            IRelationshipsDictionary resourcesByRelationship =
                CreateRelationshipHelper(node.ResourceType, ReplaceKeysWithInverseRelationships(currentResourcesGrouped));

            CallHook(container, ResourceHook.AfterUpdateRelationship, ArrayFactory.Create <object>(resourcesByRelationship, pipeline));
        }
Exemplo n.º 3
0
 public override void BeforeImplicitUpdateRelationship(IRelationshipsDictionary <Passport> resourcesByRelationship, ResourcePipeline pipeline)
 {
     resourcesByRelationship.GetByRelationship <Person>().ToList().ForEach(kvp => DoesNotTouchLockedPassports(kvp.Value));
 }
Exemplo n.º 4
0
 public override void BeforeImplicitUpdateRelationship(IRelationshipsDictionary <Person> entitiesByRelationship, ResourcePipeline pipeline)
 {
     entitiesByRelationship.GetByRelationship <Passport>().ToList().ForEach(kvp => DisallowLocked(kvp.Value));
 }
Exemplo n.º 5
0
 public override IEnumerable <string> BeforeUpdateRelationship(HashSet <string> ids, IRelationshipsDictionary <Person> entitiesByRelationship, ResourcePipeline pipeline)
 {
     BeforeImplicitUpdateRelationship(entitiesByRelationship, pipeline);
     return(ids);
 }
Exemplo n.º 6
0
 /// <inheritdoc/>
 public virtual void BeforeImplicitUpdateRelationship(IRelationshipsDictionary <T> entitiesByRelationship, ResourcePipeline pipeline)
 {
 }
Exemplo n.º 7
0
 /// <inheritdoc/>
 public virtual IEnumerable <string> BeforeUpdateRelationship(HashSet <string> ids, IRelationshipsDictionary <T> entitiesByRelationship, ResourcePipeline pipeline)
 {
     return(ids);
 }
Exemplo n.º 8
0
 /// <inheritdoc/>
 public virtual void AfterUpdateRelationship(IRelationshipsDictionary <T> entitiesByRelationship, ResourcePipeline pipeline)
 {
 }
Exemplo n.º 9
0
        public override void BeforeImplicitUpdateRelationship(IRelationshipsDictionary <TodoItem> resourcesByRelationship, ResourcePipeline pipeline)
        {
            List <TodoItem> todos = resourcesByRelationship.GetByRelationship <Person>().SelectMany(kvp => kvp.Value).ToList();

            DisallowLocked(todos);
        }
Exemplo n.º 10
0
        private bool PersonCheck(string checksum, IRelationshipsDictionary <Person> helper)
        {
            var entries = helper.GetByRelationship <TodoItem>();

            return(entries.Single().Value.Single().LastName == checksum);
        }
Exemplo n.º 11
0
 private bool TodoCheckRelationships(IRelationshipsDictionary <TodoItem> rh, string checksum)
 {
     return(rh.GetByRelationship <Person>().Single().Value.First().Description == checksum);
 }
Exemplo n.º 12
0
        private bool CheckImplicitPassports(IRelationshipsDictionary <Passport> rh)
        {
            HashSet <Passport> passports = rh.GetByRelationship <Person>().Single().Value;

            return(passports.Count == 1);
        }
Exemplo n.º 13
0
        private bool CheckImplicitTodoItems(IRelationshipsDictionary <TodoItem> rh)
        {
            IDictionary <RelationshipAttribute, HashSet <TodoItem> > todoItems = rh.GetByRelationship <Person>();

            return(todoItems.Count == 2);
        }
        private bool CheckImplicitTodos(IRelationshipsDictionary <TodoItem> rh)
        {
            var todos = rh.GetByRelationship <Person>();

            return(todos.Count == 2);
        }
Exemplo n.º 15
0
        /// <summary>
        /// Fires the nested before hooks for resources in the current <paramref name="layer" />
        /// </summary>
        /// <remarks>
        /// For example: consider the case when the owner of article1 (one-to-one) is being updated from owner_old to owner_new, where owner_new is currently
        /// already related to article2. Then, the following nested hooks need to be fired in the following order. First the BeforeUpdateRelationship should be
        /// for owner1, then the BeforeImplicitUpdateRelationship hook should be fired for owner2, and lastly the BeforeImplicitUpdateRelationship for article2.
        /// </remarks>
        private void FireNestedBeforeUpdateHooks(ResourcePipeline pipeline, IEnumerable <IResourceNode> layer)
        {
            foreach (IResourceNode node in layer)
            {
                IResourceHookContainer nestedHookContainer =
                    _containerProvider.GetResourceHookContainer(node.ResourceType, ResourceHook.BeforeUpdateRelationship);

                IEnumerable uniqueResources = node.UniqueResources;
                RightType   resourceType    = node.ResourceType;
                IDictionary <RelationshipAttribute, IEnumerable> currentResourcesGrouped;
                IDictionary <RelationshipAttribute, IEnumerable> currentResourcesGroupedInverse;

                // fire the BeforeUpdateRelationship hook for owner_new
                if (nestedHookContainer != null)
                {
                    if (uniqueResources.Cast <IIdentifiable>().Any())
                    {
                        RelationshipAttribute[] relationships = node.RelationshipsToNextLayer.Select(proxy => proxy.Attribute).ToArray();
                        IEnumerable             dbValues      = LoadDbValues(resourceType, uniqueResources, ResourceHook.BeforeUpdateRelationship, relationships);

                        // these are the resources of the current node grouped by
                        // RelationshipAttributes that occurred in the previous layer
                        // so it looks like { HasOneAttribute:owner  =>  owner_new }.
                        // Note that in the BeforeUpdateRelationship hook of Person,
                        // we want want inverse relationship attribute:
                        // we now have the one pointing from article -> person, ]
                        // but we require the the one that points from person -> article
                        currentResourcesGrouped        = node.RelationshipsFromPreviousLayer.GetRightResources();
                        currentResourcesGroupedInverse = ReplaceKeysWithInverseRelationships(currentResourcesGrouped);

                        IRelationshipsDictionary resourcesByRelationship = CreateRelationshipHelper(resourceType, currentResourcesGroupedInverse, dbValues);

                        IEnumerable <string> allowedIds = CallHook(nestedHookContainer, ResourceHook.BeforeUpdateRelationship,
                                                                   ArrayFactory.Create <object>(GetIds(uniqueResources), resourcesByRelationship, pipeline)).Cast <string>();

                        ISet <IIdentifiable> updated = GetAllowedResources(uniqueResources, allowedIds);
                        node.UpdateUnique(updated);
                        node.Reassign();
                    }
                }

                // Fire the BeforeImplicitUpdateRelationship hook for owner_old.
                // Note: if the pipeline is Post it means we just created article1,
                // which means we are sure that it isn't related to any other resources yet.
                if (pipeline != ResourcePipeline.Post)
                {
                    // To fire a hook for owner_old, we need to first get a reference to it.
                    // For this, we need to query the database for the  HasOneAttribute:owner
                    // relationship of article1, which is referred to as the
                    // left side of the HasOneAttribute:owner relationship.
                    IDictionary <RelationshipAttribute, IEnumerable> leftResources = node.RelationshipsFromPreviousLayer.GetLeftResources();

                    if (leftResources.Any())
                    {
                        // owner_old is loaded, which is an "implicitly affected resource"
                        FireForAffectedImplicits(resourceType, leftResources, pipeline, uniqueResources);
                    }
                }

                // Fire the BeforeImplicitUpdateRelationship hook for article2
                // For this, we need to query the database for the current owner
                // relationship value of owner_new.
                currentResourcesGrouped = node.RelationshipsFromPreviousLayer.GetRightResources();

                if (currentResourcesGrouped.Any())
                {
                    // rightResources is grouped by relationships from previous
                    // layer, ie { HasOneAttribute:owner  =>  owner_new }. But
                    // to load article2 onto owner_new, we need to have the
                    // RelationshipAttribute from owner to article, which is the
                    // inverse of HasOneAttribute:owner
                    currentResourcesGroupedInverse = ReplaceKeysWithInverseRelationships(currentResourcesGrouped);
                    // Note that currently in the JsonApiDotNetCore implementation of hooks,
                    // the root layer is ALWAYS homogenous, so we safely assume
                    // that for every relationship to the previous layer, the
                    // left type is the same.
                    LeftType leftType = currentResourcesGrouped.First().Key.LeftType;
                    FireForAffectedImplicits(leftType, currentResourcesGroupedInverse, pipeline);
                }
            }
        }
Exemplo n.º 16
0
        private bool PersonCheck(string checksum, IRelationshipsDictionary <Person> helper)
        {
            IDictionary <RelationshipAttribute, HashSet <Person> > entries = helper.GetByRelationship <TodoItem>();

            return(entries.Single().Value.Single().Name == checksum);
        }