Пример #1
0
        public Task <IResourceLinkage> Deserialize(JsonReader reader, string currentPath)
        {
            IResourceLinkage linkage;

            if (reader.TokenType == JsonToken.StartArray)
            {
                var array = JToken.ReadFrom(reader);
                var resourceIdentifiers = array.Select(t => ReadResourceIdentifier(t, currentPath)).ToArray();

                linkage = new ToManyResourceLinkage(resourceIdentifiers);
            }
            else if (reader.TokenType == JsonToken.StartObject)
            {
                var obj = JToken.ReadFrom(reader);
                var resourceIdentifier = ReadResourceIdentifier(obj, currentPath);

                linkage = new ToOneResourceLinkage(resourceIdentifier);
            }
            else if (reader.TokenType == JsonToken.Null)
            {
                linkage = new ToOneResourceLinkage(null);
            }
            else
            {
                throw new DeserializationException("Invalid linkage for relationship",
                                                   "Expected an array, object, or null for linkage, but got " + reader.TokenType, currentPath);
            }

            return(Task.FromResult(linkage));
        }
        public void Identifiers_is_correct_for_present_identifiers()
        {
            var mockIdentifier1 = new Mock <IResourceIdentifier>(MockBehavior.Strict);

            mockIdentifier1.Setup(i => i.Type).Returns("countries");
            mockIdentifier1.Setup(i => i.Id).Returns("1000");

            var mockIdentifier2 = new Mock <IResourceIdentifier>(MockBehavior.Strict);

            mockIdentifier2.Setup(i => i.Type).Returns("cities");
            mockIdentifier2.Setup(i => i.Id).Returns("4000");

            var linkage = new ToManyResourceLinkage(new [] { mockIdentifier1.Object, mockIdentifier2.Object });

            linkage.Identifiers.Length.Should().Be(2);
            linkage.Identifiers[0].Type.Should().Be("countries");
            linkage.Identifiers[0].Id.Should().Be("1000");
            linkage.Identifiers[1].Type.Should().Be("cities");
            linkage.Identifiers[1].Id.Should().Be("4000");
        }
        /// <summary>
        /// Creates a JSON API resource object from the given CLR object
        /// </summary>
        /// <param name="modelObject"></param>
        /// <param name="idDictionariesByType"></param>
        /// <param name="currentPath"></param>
        /// <param name="includePathExpressions"></param>
        /// <param name="linkBaseUrl"></param>
        /// <returns></returns>
        protected ResourceObject CreateResourceObject(object modelObject, IDictionary<string, IDictionary<string, ResourceObject>> idDictionariesByType,
            string currentPath, string[] includePathExpressions, string linkBaseUrl)
        {
            if (modelObject == null) return null;

            var modelObjectRuntimeType = modelObject.GetType();
            var resourceTypeRegistration = _resourceTypeRegistry.GetRegistrationForType(modelObjectRuntimeType);

            var attributes = new Dictionary<string, JToken>();
            var relationships = new Dictionary<string, IRelationshipObject>();

            foreach (var attribute in resourceTypeRegistration.Attributes)
            {
                var propertyValue = attribute.GetValue(modelObject);
                attributes[attribute.JsonKey] = propertyValue;
            }

            foreach (var modelRelationship in resourceTypeRegistration.Relationships)
            {
                IResourceLinkage linkage = null;

                var childPath = currentPath == null
                    ? modelRelationship.JsonKey
                    : (currentPath + "." + modelRelationship.JsonKey);
                if (includePathExpressions != null &&
                    includePathExpressions.Any(e => PathExpressionMatchesCurrentPath(childPath, e)))
                {
                    if (modelRelationship.IsToMany)
                    {
                        var propertyValue =
                            (IEnumerable<object>)modelRelationship.Property.GetValue(modelObject);
                        if (propertyValue != null)
                        {
                            var identifiers = new List<IResourceIdentifier>();
                            foreach (var relatedResource in propertyValue)
                            {
                                var identifier = GetResourceIdentifierForResource(relatedResource);
                                identifiers.Add(identifier);

                                IDictionary<string, ResourceObject> idDictionary;
                                if (!idDictionariesByType.TryGetValue(identifier.Type, out idDictionary))
                                {
                                    idDictionary = new Dictionary<string, ResourceObject>();
                                    idDictionariesByType[identifier.Type] = idDictionary;
                                }

                                ResourceObject relatedResourceObject;
                                if (!idDictionary.TryGetValue(identifier.Id, out relatedResourceObject))
                                {
                                    relatedResourceObject = CreateResourceObject(relatedResource, idDictionariesByType,
                                        childPath, includePathExpressions, linkBaseUrl);
                                    idDictionary[identifier.Id] = relatedResourceObject;
                                }
                            }
                            linkage = new ToManyResourceLinkage(identifiers.ToArray());
                        }
                    }
                    else
                    {
                        var relatedResource = modelRelationship.Property.GetValue(modelObject);
                        if (relatedResource != null)
                        {
                            var identifier = GetResourceIdentifierForResource(relatedResource);

                            IDictionary<string, ResourceObject> idDictionary;
                            if (!idDictionariesByType.TryGetValue(identifier.Type, out idDictionary))
                            {
                                idDictionary = new Dictionary<string, ResourceObject>();
                                idDictionariesByType[identifier.Type] = idDictionary;
                            }

                            ResourceObject relatedResourceObject;
                            if (!idDictionary.TryGetValue(identifier.Id, out relatedResourceObject))
                            {
                                relatedResourceObject = CreateResourceObject(relatedResource, idDictionariesByType,
                                    childPath, includePathExpressions, linkBaseUrl);
                                idDictionary[identifier.Id] = relatedResourceObject;
                            }

                            linkage = new ToOneResourceLinkage(identifier);
                        }
                        else
                        {
                            linkage = new ToOneResourceLinkage(null);
                        }
                    }
                }

                var selfLink = _linkConventions.GetRelationshipLink(modelObject, _resourceTypeRegistry, modelRelationship, linkBaseUrl);
                var relatedResourceLink = _linkConventions.GetRelatedResourceLink(modelObject, _resourceTypeRegistry, modelRelationship, linkBaseUrl);

                relationships[modelRelationship.JsonKey] = new RelationshipObject(linkage, selfLink, relatedResourceLink);
            }

            var resourceId = resourceTypeRegistration.GetIdForResource(modelObject);
            return new ResourceObject(resourceTypeRegistration.ResourceTypeName, resourceId, attributes, relationships);
        }
        public void Returns_corrent_LinkageToken_for_empty_identifiers()
        {
            var linkage = new ToManyResourceLinkage(new IResourceIdentifier[] { });

            linkage.Identifiers.Length.Should().Be(0);
        }
        public void Returns_corrent_LinkageToken_for_null_identifiers()
        {
            var linkage = new ToManyResourceLinkage(null);

            linkage.Identifiers.Length.Should().Be(0);
        }
        /// <summary>
        /// Creates a JSON API resource object from the given CLR object
        /// </summary>
        /// <param name="modelObject"></param>
        /// <param name="idDictionariesByType"></param>
        /// <param name="currentPath"></param>
        /// <param name="includePathExpressions"></param>
        /// <param name="linkBaseUrl"></param>
        /// <param name="resourceObjectMetadata"></param>
        /// <returns></returns>
        protected ResourceObject CreateResourceObject(object modelObject, IDictionary <string, IDictionary <string, ResourceObject> > idDictionariesByType,
                                                      string currentPath, string[] includePathExpressions, string linkBaseUrl, IDictionary <object, IMetadata> resourceObjectMetadata)
        {
            if (modelObject == null)
            {
                return(null);
            }

            var modelObjectRuntimeType   = modelObject.GetType();
            var resourceTypeRegistration = _resourceTypeRegistry.GetRegistrationForType(modelObjectRuntimeType);

            var attributes    = new Dictionary <string, JToken>();
            var relationships = new Dictionary <string, IRelationshipObject>();

            foreach (var attribute in resourceTypeRegistration.Attributes)
            {
                var propertyValue = attribute.GetValue(modelObject);
                attributes[attribute.JsonKey] = propertyValue;
            }

            foreach (var modelRelationship in resourceTypeRegistration.Relationships)
            {
                IResourceLinkage linkage = null;

                var childPath = currentPath == null
                    ? modelRelationship.JsonKey
                    : (currentPath + "." + modelRelationship.JsonKey);
                if (includePathExpressions != null &&
                    includePathExpressions.Any(e => PathExpressionMatchesCurrentPath(childPath, e)))
                {
                    if (modelRelationship.IsToMany)
                    {
                        var propertyValue =
                            (IEnumerable <object>)modelRelationship.Property.GetValue(modelObject);
                        if (propertyValue != null)
                        {
                            var identifiers = new List <IResourceIdentifier>();
                            foreach (var relatedResource in propertyValue)
                            {
                                var identifier = GetResourceIdentifierForResource(relatedResource);
                                identifiers.Add(identifier);

                                IDictionary <string, ResourceObject> idDictionary;
                                if (!idDictionariesByType.TryGetValue(identifier.Type, out idDictionary))
                                {
                                    idDictionary = new Dictionary <string, ResourceObject>();
                                    idDictionariesByType[identifier.Type] = idDictionary;
                                }

                                ResourceObject relatedResourceObject;
                                if (!idDictionary.TryGetValue(identifier.Id, out relatedResourceObject))
                                {
                                    relatedResourceObject = CreateResourceObject(relatedResource, idDictionariesByType,
                                                                                 childPath, includePathExpressions, linkBaseUrl, resourceObjectMetadata);
                                    idDictionary[identifier.Id] = relatedResourceObject;
                                }
                            }
                            linkage = new ToManyResourceLinkage(identifiers.ToArray());
                        }
                    }
                    else
                    {
                        var relatedResource = modelRelationship.Property.GetValue(modelObject);
                        if (relatedResource != null)
                        {
                            var identifier = GetResourceIdentifierForResource(relatedResource);

                            IDictionary <string, ResourceObject> idDictionary;
                            if (!idDictionariesByType.TryGetValue(identifier.Type, out idDictionary))
                            {
                                idDictionary = new Dictionary <string, ResourceObject>();
                                idDictionariesByType[identifier.Type] = idDictionary;
                            }

                            ResourceObject relatedResourceObject;
                            if (!idDictionary.TryGetValue(identifier.Id, out relatedResourceObject))
                            {
                                relatedResourceObject = CreateResourceObject(relatedResource, idDictionariesByType,
                                                                             childPath, includePathExpressions, linkBaseUrl, resourceObjectMetadata);
                                idDictionary[identifier.Id] = relatedResourceObject;
                            }

                            linkage = new ToOneResourceLinkage(identifier);
                        }
                        else
                        {
                            linkage = new ToOneResourceLinkage(null);
                        }
                    }
                }

                var selfLink            = _linkConventions.GetRelationshipLink(modelObject, _resourceTypeRegistry, modelRelationship, linkBaseUrl);
                var relatedResourceLink = _linkConventions.GetRelatedResourceLink(modelObject, _resourceTypeRegistry, modelRelationship, linkBaseUrl);

                relationships[modelRelationship.JsonKey] = new RelationshipObject(linkage, selfLink, relatedResourceLink);
            }

            var resourceId = resourceTypeRegistration.GetIdForResource(modelObject);

            IMetadata thisResourceObjectsMetadata;

            if (resourceObjectMetadata != null)
            {
                resourceObjectMetadata.TryGetValue(modelObject, out thisResourceObjectsMetadata);
            }
            else
            {
                thisResourceObjectsMetadata = null;
            }
            return(new ResourceObject(resourceTypeRegistration.ResourceTypeName, resourceId, attributes, relationships, metadata: thisResourceObjectsMetadata));
        }