Example #1
0
        private static void UpdateNamedStreamMetadata(XElement link, PayloadNamedStream namedStream)
        {
            XAttribute typeAttribute  = link.Attribute("type");
            XAttribute titleAttribute = link.Attribute("title");
            XAttribute etagAttribute  = link.Attribute("etag");


            if (typeAttribute != null)
            {
                namedStream.ContentType = typeAttribute.Value;
            }

            if (titleAttribute != null)
            {
                namedStream.Title = titleAttribute.Value;
            }


            if (etagAttribute != null)
            {
                namedStream.ETag = etagAttribute.Value;
            }
        }
Example #2
0
        private PayloadObject parseJsonObject(JSObject jsObject)
        {
            PayloadObject payloadObject = new PayloadObject(this);

            FieldInfo[] fields = jsObject.GetFields(BindingFlags.Default);

            for (int i = 0; i < fields.Length; i++)
            {
                JSField field = (JSField)fields[i];
                var value = field.GetValue(field);

                if (value is ArrayObject)
                {
                    PayloadObject payloadNestedParentObject = new PayloadObject(this);
                    payloadNestedParentObject.Name = field.Name;

                    ArrayObject nestedPayloadObjects = (ArrayObject)field.GetValue(field);
                    payloadNestedParentObject.PayloadObjects.AddRange(this.ParseJsonArray(nestedPayloadObjects));

                    foreach (PayloadObject po in payloadNestedParentObject.PayloadObjects)
                    {
                        po.Name = field.Name;
                    }

                    payloadObject.PayloadObjects.Add(payloadNestedParentObject);
                }
                else if (value is JSObject)
                {
                    if (field.Name == "__metadata")
                    {
                        payloadObject.Uri = this.GetArrayString(field, "uri");
                        payloadObject.Type = this.GetArrayString(field, "type");

                        string etag = this.GetArrayString(field, "etag");
                        if (etag != null)
                        {
                            payloadObject.ETag = etag;
                        }
                    }
                    else
                    {
                        JSField firstChild = this.GetArrayField(field, 0);

                        if (firstChild != null && firstChild.Name == v2JsonResultsField)
                        {
                            PayloadObject payloadNestedParentObject = new PayloadObject(this);
                            payloadNestedParentObject.Name = field.Name;

                            ArrayObject nestedPayloadObjects = (ArrayObject)firstChild.GetValue(firstChild);
                            payloadNestedParentObject.PayloadObjects.AddRange(this.ParseJsonArray(nestedPayloadObjects));

                            foreach (PayloadObject po in payloadNestedParentObject.PayloadObjects)
                            {
                                po.Name = field.Name;
                            }

                            payloadObject.PayloadObjects.Add(payloadNestedParentObject);
                        }
                        else if (firstChild != null && firstChild.Name == "__deferred") // Deferred reference/collection
                        {
                            PayloadObject deferredObject = new PayloadObject(this);
                            deferredObject.Name = field.Name;
                            deferredObject.Uri = this.GetArrayString(firstChild, "uri");
                            deferredObject.Deferred = true;

                            payloadObject.PayloadObjects.Add(deferredObject);
                        }
                        else if (firstChild != null && firstChild.Name == "__mediaresource")
                        {
                            PayloadNamedStream stream = new PayloadNamedStream();
                            stream.Name = field.Name;
                            stream.ContentType = this.GetArrayString(firstChild, "content-type");
                            stream.EditLink = this.GetArrayString(firstChild, "edit_media");
                            stream.SelfLink = this.GetArrayString(firstChild, "media_src");
                            stream.ETag = this.GetArrayString(firstChild, "etag");
                            payloadObject.NamedStreams.Add(stream);
                        }
                        else
                        {
                            JSObject objectValue = (JSObject)field.GetValue(field);
                            var objectValueFields = objectValue.GetFields(BindingFlags.Default);
                            if (objectValueFields.Any(f => f.Name == "__metadata" && GetArrayString((JSField)f, "uri") != null))
                            {
                                PayloadObject referencePayloadObject = parseJsonObject(objectValue);
                                referencePayloadObject.Name = field.Name;
                                referencePayloadObject.Reference = true;

                                payloadObject.PayloadObjects.Add(referencePayloadObject);
                            }
                            else
                            {
                                PayloadComplexProperty payloadProperty = this.parseComplexObject(payloadObject, field);    // Complex object
                                payloadObject.PayloadProperties.Add(payloadProperty);
                            }
                        }
                    }
                }
                else
                {
                    PayloadProperty payloadProperty = this.parseSimpleObject(payloadObject, field);
                    payloadObject.PayloadProperties.Add(payloadProperty);
                }
            }

            return payloadObject;
        }
Example #3
0
        private static void UpdateNamedStreamMetadata(XElement link, PayloadNamedStream namedStream)
        {
            XAttribute typeAttribute = link.Attribute("type");
            XAttribute titleAttribute = link.Attribute("title");
            XAttribute etagAttribute = link.Attribute("etag");


            if (typeAttribute != null)
            {
                namedStream.ContentType = typeAttribute.Value;
            }

            if (titleAttribute != null)
            {
                namedStream.Title = titleAttribute.Value;
            }


            if (etagAttribute != null)
            {
                namedStream.ETag = etagAttribute.Value;
            }
        }
Example #4
0
        internal PayloadObject ParseEntry(XElement xmlData)
        {
            PayloadObject payloadObject = new PayloadObject(this);

            #region edit link
            XElement linkEdit = xmlData.Elements(atom + "link").SingleOrDefault(l => l.Attribute("rel") != null && l.Attribute("rel").Value == "edit");
            if (linkEdit != null)
                payloadObject.Uri = linkEdit.Attribute("href").Value;
            #endregion

            #region id link
            XElement idNode = xmlData.Element(atom + "id");
            if (idNode != null)
                payloadObject.Uri = idNode.Value;
            // TODO: compare the edit link to the ID node's value
            #endregion

            #region name
            XElement titleNode = xmlData.Parent;
            if (titleNode != null && titleNode.Name == m + "inline")
            {
                XAttribute titleAttribute = titleNode.Parent.Attribute("title");
                if (titleAttribute != null)
                    payloadObject.Name = titleAttribute.Value;
            }
            else if (titleNode != null)
            {
                titleNode = titleNode.Element(atom + "title");
                if (titleNode != null)
                    payloadObject.Name = titleNode.Value;
            }
            else if (linkEdit != null)
            {
                XAttribute titleAttribute = linkEdit.Attribute("title");
                if (titleAttribute != null)
                    payloadObject.Name = titleAttribute.Value;
            }
            #endregion

            #region type
            bool isMediaLink = false;
            XElement category = xmlData.Element(atom + "category");
            ResourceType type = null;
            if (category != null)
            {
                XAttribute term = category.Attribute("term");
                if (term != null)
                {
                    payloadObject.Type = term.Value;
                    type = Workspace.ServiceContainer.ResourceTypes.Single(rt => rt.Namespace + "." + rt.Name == term.Value);
                    if (type.Facets.HasStream)
                        isMediaLink = true;
                }
            }
            #endregion

            #region friendly feeds
            ParseNullableSyndicationItemProperty(AtomSyndicationItemProperty.Title, xmlData, payloadObject);
            ParseNullableSyndicationItemProperty(AtomSyndicationItemProperty.Summary, xmlData, payloadObject);
            ParseNullableSyndicationItemProperty(AtomSyndicationItemProperty.Rights, xmlData, payloadObject);

            //This is the correct mapping for Friendly Feeds SyndicationItemProperty.Published
            XElement ffEntryPublishedNode = xmlData.Element(atom + "published");
            if (ffEntryPublishedNode != null)
                payloadObject.SyndicationItemProperties[AtomSyndicationItemProperty.Published] = ffEntryPublishedNode.Value;

            //This is the correct mapping for Friendly Feeds SyndicationItemProperty.Updated
            XElement ffEntryUpdatedNode = xmlData.Element(atom + "updated");
            if (ffEntryUpdatedNode != null)
                payloadObject.SyndicationItemProperties[AtomSyndicationItemProperty.Updated] = ffEntryUpdatedNode.Value;

            //This is the correct mapping for Friendly Feeds Author Node
            XElement ffEntryAuthorNode = xmlData.Element(atom + "author");
            if (ffEntryAuthorNode != null)
            {
                //Friendly Feeds SyndicationItemProperty.AuthorEmail
                XElement ffEmailNode = ffEntryAuthorNode.Element(atom + "email");
                if (ffEmailNode != null)
                    payloadObject.SyndicationItemProperties[AtomSyndicationItemProperty.AuthorEmail] = ffEmailNode.Value;

                //Friendly Feeds SyndicationItemProperty.AuthorName
                XElement ffNameNode = ffEntryAuthorNode.Element(atom + "name");
                if (ffNameNode != null)
                    payloadObject.SyndicationItemProperties[AtomSyndicationItemProperty.AuthorName] = ffNameNode.Value;

                //Friendly Feeds SyndicationItemProperty.AuthorUri
                XElement ffUriNode = ffEntryAuthorNode.Element(atom + "uri");
                if (ffUriNode != null)
                    payloadObject.SyndicationItemProperties[AtomSyndicationItemProperty.AuthorUri] = ffUriNode.Value;
            }

            //This is the correct mapping for Friendly Feeds Contributor Node
            XElement ffEntryContributorNode = xmlData.Element(atom + "contributor");
            if (ffEntryContributorNode != null)
            {
                //Friendly Feeds SyndicationItemProperty.ContributorEmail
                XElement ffEmailNode = ffEntryContributorNode.Element(atom + "email");
                if (ffEmailNode != null)
                    payloadObject.SyndicationItemProperties[AtomSyndicationItemProperty.ContributorEmail] = ffEmailNode.Value;

                //Friendly Feeds SyndicationItemProperty.ContributorName
                XElement ffNameNode = ffEntryContributorNode.Element(atom + "name");
                if (ffNameNode != null)
                    payloadObject.SyndicationItemProperties[AtomSyndicationItemProperty.ContributorName] = ffNameNode.Value;

                //Friendly Feeds SyndicationItemProperty.ContributorUri
                XElement ffUriNode = ffEntryContributorNode.Element(atom + "uri");
                if (ffUriNode != null)
                    payloadObject.SyndicationItemProperties[AtomSyndicationItemProperty.ContributorUri] = ffUriNode.Value;
            }

            #endregion

            #region etag
            if (xmlData.HasAttributes)
            {
                XAttribute etagNodeAttribute = xmlData.Attribute(m + "etag");
                if (etagNodeAttribute != null)
                    payloadObject.ETag = etagNodeAttribute.Value;
            }
            #endregion

            #region properties
            XElement content = xmlData.Element(atom + "content");
            XElement properties = null;
            if (content != null)
            {
                XAttribute contentType = content.Attribute("type");
                if (contentType != null)
                {
                    if (!isMediaLink)
                    {
                        StringComparison comp;
                        if (WasResponse)
                            comp = StringComparison.InvariantCulture;
                        else
                            comp = StringComparison.InvariantCultureIgnoreCase;
                        if (!contentType.Value.Equals("application/xml", comp))
                            AstoriaTestLog.AreEqual("application/xml", contentType.Value, "Unexpected type on content element", true);
                        properties = content.Element(m + "properties");
                    }
                    // TODO: save content type if its a media link
                }
            }

            if (isMediaLink)
                properties = xmlData.Element(m + "properties");

            if (properties != null)
            {
                foreach (XElement element in properties.Elements())
                {
                    PayloadProperty property;
                    if (element.HasElements)
                    {
                        property = ParseComplexProperty(payloadObject, element);
                    }
                    else
                    {
                        property = ParseSimpleProperty(payloadObject, element);
                    }
                    payloadObject.PayloadProperties.Add(property);
                }
            }
            #endregion

            #region links
            foreach (XElement link in xmlData.Elements(atom + "link"))
            {
                Uri linkRel = new Uri(link.Attribute("rel").Value, UriKind.RelativeOrAbsolute);
                if (linkRel.IsAbsoluteUri)
                {
                    string linkRelValue = linkRel.GetComponents(UriComponents.AbsoluteUri, UriFormat.SafeUnescaped);
                    if (linkRelValue.StartsWith(DataWebRelatedNamespace, StringComparison.Ordinal))
                    {
                        XElement inlineTag = link.Element(m + "inline");
                        if (inlineTag != null)
                        {
                            PayloadObject nestedPayloadObject = new PayloadObject(this);
                            nestedPayloadObject.Name = linkRelValue.Substring(DataWebRelatedNamespace.Length);

                            string linkType = link.Attribute("type").Value;
                            if (linkType.Contains("feed"))
                            {
                                if (inlineTag.HasElements)
                                    nestedPayloadObject.PayloadObjects.AddRange(this.ParseFeed(inlineTag.Elements().Single()));
                            }
                            else if (linkType.Contains("entry"))
                            {
                                if (inlineTag.HasElements)
                                    nestedPayloadObject = this.ParseEntry(inlineTag.Elements().Single());

                                nestedPayloadObject.Reference = true;
                            }

                            payloadObject.PayloadObjects.Add(nestedPayloadObject);
                        }
                        else
                        {
                            // deferred links
                            PayloadObject deferredObject = new PayloadObject(this);
                            deferredObject.Name = linkRelValue.Substring(DataWebRelatedNamespace.Length);
                            if (link.Attribute("href") != null)
                                deferredObject.Uri = link.Attribute("href").Value;
                            deferredObject.Deferred = true;

                            payloadObject.PayloadObjects.Add(deferredObject);
                        }
                    }
                    else if (linkRelValue.StartsWith(DataWebMediaResourceNamespace))
                    {
                        string name = linkRelValue.Substring(DataWebMediaResourceNamespace.Length);
                        PayloadNamedStream namedStream = payloadObject.NamedStreams.SingleOrDefault(s => s.Name == name);
                        if (namedStream == null)
                        {
                            namedStream = new PayloadNamedStream() { Name = name };
                            payloadObject.NamedStreams.Add(namedStream);
                        }

                        UpdateNamedStreamMetadata(link, namedStream);
                        namedStream.SelfLink = link.Attribute("href").Value;
                    }
                    else if (linkRelValue.StartsWith(DataWebMediaResourceEditNamespace))
                    {
                        string name = linkRelValue.Substring(DataWebMediaResourceEditNamespace.Length);
                        PayloadNamedStream namedStream = payloadObject.NamedStreams.SingleOrDefault(s => s.Name == name);
                        if (namedStream == null)
                        {
                            namedStream = new PayloadNamedStream() { Name = name };
                            payloadObject.NamedStreams.Add(namedStream);
                        }

                        UpdateNamedStreamMetadata(link, namedStream);
                        namedStream.EditLink = link.Attribute("href").Value;
                    }
                }
            }
            #endregion

            return payloadObject;
        }
Example #5
0
        private PayloadObject parseJsonObject(JSObject jsObject)
        {
            PayloadObject payloadObject = new PayloadObject(this);

            FieldInfo[] fields = jsObject.GetFields(BindingFlags.Default);

            for (int i = 0; i < fields.Length; i++)
            {
                JSField field = (JSField)fields[i];
                var     value = field.GetValue(field);

                if (value is ArrayObject)
                {
                    PayloadObject payloadNestedParentObject = new PayloadObject(this);
                    payloadNestedParentObject.Name = field.Name;

                    ArrayObject nestedPayloadObjects = (ArrayObject)field.GetValue(field);
                    payloadNestedParentObject.PayloadObjects.AddRange(this.ParseJsonArray(nestedPayloadObjects));

                    foreach (PayloadObject po in payloadNestedParentObject.PayloadObjects)
                    {
                        po.Name = field.Name;
                    }

                    payloadObject.PayloadObjects.Add(payloadNestedParentObject);
                }
                else if (value is JSObject)
                {
                    if (field.Name == "__metadata")
                    {
                        payloadObject.Uri  = this.GetArrayString(field, "uri");
                        payloadObject.Type = this.GetArrayString(field, "type");

                        string etag = this.GetArrayString(field, "etag");
                        if (etag != null)
                        {
                            payloadObject.ETag = etag;
                        }
                    }
                    else
                    {
                        JSField firstChild = this.GetArrayField(field, 0);

                        if (firstChild != null && firstChild.Name == v2JsonResultsField)
                        {
                            PayloadObject payloadNestedParentObject = new PayloadObject(this);
                            payloadNestedParentObject.Name = field.Name;

                            ArrayObject nestedPayloadObjects = (ArrayObject)firstChild.GetValue(firstChild);
                            payloadNestedParentObject.PayloadObjects.AddRange(this.ParseJsonArray(nestedPayloadObjects));

                            foreach (PayloadObject po in payloadNestedParentObject.PayloadObjects)
                            {
                                po.Name = field.Name;
                            }

                            payloadObject.PayloadObjects.Add(payloadNestedParentObject);
                        }
                        else if (firstChild != null && firstChild.Name == "__deferred") // Deferred reference/collection
                        {
                            PayloadObject deferredObject = new PayloadObject(this);
                            deferredObject.Name     = field.Name;
                            deferredObject.Uri      = this.GetArrayString(firstChild, "uri");
                            deferredObject.Deferred = true;

                            payloadObject.PayloadObjects.Add(deferredObject);
                        }
                        else if (firstChild != null && firstChild.Name == "__mediaresource")
                        {
                            PayloadNamedStream stream = new PayloadNamedStream();
                            stream.Name        = field.Name;
                            stream.ContentType = this.GetArrayString(firstChild, "content-type");
                            stream.EditLink    = this.GetArrayString(firstChild, "edit_media");
                            stream.SelfLink    = this.GetArrayString(firstChild, "media_src");
                            stream.ETag        = this.GetArrayString(firstChild, "etag");
                            payloadObject.NamedStreams.Add(stream);
                        }
                        else
                        {
                            JSObject objectValue       = (JSObject)field.GetValue(field);
                            var      objectValueFields = objectValue.GetFields(BindingFlags.Default);
                            if (objectValueFields.Any(f => f.Name == "__metadata" && GetArrayString((JSField)f, "uri") != null))
                            {
                                PayloadObject referencePayloadObject = parseJsonObject(objectValue);
                                referencePayloadObject.Name      = field.Name;
                                referencePayloadObject.Reference = true;

                                payloadObject.PayloadObjects.Add(referencePayloadObject);
                            }
                            else
                            {
                                PayloadComplexProperty payloadProperty = this.parseComplexObject(payloadObject, field);    // Complex object
                                payloadObject.PayloadProperties.Add(payloadProperty);
                            }
                        }
                    }
                }
                else
                {
                    PayloadProperty payloadProperty = this.parseSimpleObject(payloadObject, field);
                    payloadObject.PayloadProperties.Add(payloadProperty);
                }
            }

            return(payloadObject);
        }
Example #6
0
        internal PayloadObject ParseEntry(XElement xmlData)
        {
            PayloadObject payloadObject = new PayloadObject(this);

            #region edit link
            XElement linkEdit = xmlData.Elements(atom + "link").SingleOrDefault(l => l.Attribute("rel") != null && l.Attribute("rel").Value == "edit");
            if (linkEdit != null)
            {
                payloadObject.Uri = linkEdit.Attribute("href").Value;
            }
            #endregion

            #region id link
            XElement idNode = xmlData.Element(atom + "id");
            if (idNode != null)
            {
                payloadObject.Uri = idNode.Value;
            }
            // TODO: compare the edit link to the ID node's value
            #endregion

            #region name
            XElement titleNode = xmlData.Parent;
            if (titleNode != null && titleNode.Name == m + "inline")
            {
                XAttribute titleAttribute = titleNode.Parent.Attribute("title");
                if (titleAttribute != null)
                {
                    payloadObject.Name = titleAttribute.Value;
                }
            }
            else if (titleNode != null)
            {
                titleNode = titleNode.Element(atom + "title");
                if (titleNode != null)
                {
                    payloadObject.Name = titleNode.Value;
                }
            }
            else if (linkEdit != null)
            {
                XAttribute titleAttribute = linkEdit.Attribute("title");
                if (titleAttribute != null)
                {
                    payloadObject.Name = titleAttribute.Value;
                }
            }
            #endregion

            #region type
            bool         isMediaLink = false;
            XElement     category    = xmlData.Element(atom + "category");
            ResourceType type        = null;
            if (category != null)
            {
                XAttribute term = category.Attribute("term");
                if (term != null)
                {
                    payloadObject.Type = term.Value;
                    type = Workspace.ServiceContainer.ResourceTypes.Single(rt => rt.Namespace + "." + rt.Name == term.Value);
                    if (type.Facets.HasStream)
                    {
                        isMediaLink = true;
                    }
                }
            }
            #endregion

            #region friendly feeds
            ParseNullableSyndicationItemProperty(AtomSyndicationItemProperty.Title, xmlData, payloadObject);
            ParseNullableSyndicationItemProperty(AtomSyndicationItemProperty.Summary, xmlData, payloadObject);
            ParseNullableSyndicationItemProperty(AtomSyndicationItemProperty.Rights, xmlData, payloadObject);

            //This is the correct mapping for Friendly Feeds SyndicationItemProperty.Published
            XElement ffEntryPublishedNode = xmlData.Element(atom + "published");
            if (ffEntryPublishedNode != null)
            {
                payloadObject.SyndicationItemProperties[AtomSyndicationItemProperty.Published] = ffEntryPublishedNode.Value;
            }

            //This is the correct mapping for Friendly Feeds SyndicationItemProperty.Updated
            XElement ffEntryUpdatedNode = xmlData.Element(atom + "updated");
            if (ffEntryUpdatedNode != null)
            {
                payloadObject.SyndicationItemProperties[AtomSyndicationItemProperty.Updated] = ffEntryUpdatedNode.Value;
            }

            //This is the correct mapping for Friendly Feeds Author Node
            XElement ffEntryAuthorNode = xmlData.Element(atom + "author");
            if (ffEntryAuthorNode != null)
            {
                //Friendly Feeds SyndicationItemProperty.AuthorEmail
                XElement ffEmailNode = ffEntryAuthorNode.Element(atom + "email");
                if (ffEmailNode != null)
                {
                    payloadObject.SyndicationItemProperties[AtomSyndicationItemProperty.AuthorEmail] = ffEmailNode.Value;
                }

                //Friendly Feeds SyndicationItemProperty.AuthorName
                XElement ffNameNode = ffEntryAuthorNode.Element(atom + "name");
                if (ffNameNode != null)
                {
                    payloadObject.SyndicationItemProperties[AtomSyndicationItemProperty.AuthorName] = ffNameNode.Value;
                }

                //Friendly Feeds SyndicationItemProperty.AuthorUri
                XElement ffUriNode = ffEntryAuthorNode.Element(atom + "uri");
                if (ffUriNode != null)
                {
                    payloadObject.SyndicationItemProperties[AtomSyndicationItemProperty.AuthorUri] = ffUriNode.Value;
                }
            }

            //This is the correct mapping for Friendly Feeds Contributor Node
            XElement ffEntryContributorNode = xmlData.Element(atom + "contributor");
            if (ffEntryContributorNode != null)
            {
                //Friendly Feeds SyndicationItemProperty.ContributorEmail
                XElement ffEmailNode = ffEntryContributorNode.Element(atom + "email");
                if (ffEmailNode != null)
                {
                    payloadObject.SyndicationItemProperties[AtomSyndicationItemProperty.ContributorEmail] = ffEmailNode.Value;
                }

                //Friendly Feeds SyndicationItemProperty.ContributorName
                XElement ffNameNode = ffEntryContributorNode.Element(atom + "name");
                if (ffNameNode != null)
                {
                    payloadObject.SyndicationItemProperties[AtomSyndicationItemProperty.ContributorName] = ffNameNode.Value;
                }

                //Friendly Feeds SyndicationItemProperty.ContributorUri
                XElement ffUriNode = ffEntryContributorNode.Element(atom + "uri");
                if (ffUriNode != null)
                {
                    payloadObject.SyndicationItemProperties[AtomSyndicationItemProperty.ContributorUri] = ffUriNode.Value;
                }
            }

            #endregion

            #region etag
            if (xmlData.HasAttributes)
            {
                XAttribute etagNodeAttribute = xmlData.Attribute(m + "etag");
                if (etagNodeAttribute != null)
                {
                    payloadObject.ETag = etagNodeAttribute.Value;
                }
            }
            #endregion

            #region properties
            XElement content    = xmlData.Element(atom + "content");
            XElement properties = null;
            if (content != null)
            {
                XAttribute contentType = content.Attribute("type");
                if (contentType != null)
                {
                    if (!isMediaLink)
                    {
                        StringComparison comp;
                        if (WasResponse)
                        {
                            comp = StringComparison.InvariantCulture;
                        }
                        else
                        {
                            comp = StringComparison.InvariantCultureIgnoreCase;
                        }
                        if (!contentType.Value.Equals("application/xml", comp))
                        {
                            AstoriaTestLog.AreEqual("application/xml", contentType.Value, "Unexpected type on content element", true);
                        }
                        properties = content.Element(m + "properties");
                    }
                    // TODO: save content type if its a media link
                }
            }

            if (isMediaLink)
            {
                properties = xmlData.Element(m + "properties");
            }

            if (properties != null)
            {
                foreach (XElement element in properties.Elements())
                {
                    PayloadProperty property;
                    if (element.HasElements)
                    {
                        property = ParseComplexProperty(payloadObject, element);
                    }
                    else
                    {
                        property = ParseSimpleProperty(payloadObject, element);
                    }
                    payloadObject.PayloadProperties.Add(property);
                }
            }
            #endregion

            #region links
            foreach (XElement link in xmlData.Elements(atom + "link"))
            {
                Uri linkRel = new Uri(link.Attribute("rel").Value, UriKind.RelativeOrAbsolute);
                if (linkRel.IsAbsoluteUri)
                {
                    string linkRelValue = linkRel.GetComponents(UriComponents.AbsoluteUri, UriFormat.SafeUnescaped);
                    if (linkRelValue.StartsWith(DataWebRelatedNamespace, StringComparison.Ordinal))
                    {
                        XElement inlineTag = link.Element(m + "inline");
                        if (inlineTag != null)
                        {
                            PayloadObject nestedPayloadObject = new PayloadObject(this);
                            nestedPayloadObject.Name = linkRelValue.Substring(DataWebRelatedNamespace.Length);

                            string linkType = link.Attribute("type").Value;
                            if (linkType.Contains("feed"))
                            {
                                if (inlineTag.HasElements)
                                {
                                    nestedPayloadObject.PayloadObjects.AddRange(this.ParseFeed(inlineTag.Elements().Single()));
                                }
                            }
                            else if (linkType.Contains("entry"))
                            {
                                if (inlineTag.HasElements)
                                {
                                    nestedPayloadObject = this.ParseEntry(inlineTag.Elements().Single());
                                }

                                nestedPayloadObject.Reference = true;
                            }

                            payloadObject.PayloadObjects.Add(nestedPayloadObject);
                        }
                        else
                        {
                            // deferred links
                            PayloadObject deferredObject = new PayloadObject(this);
                            deferredObject.Name = linkRelValue.Substring(DataWebRelatedNamespace.Length);
                            if (link.Attribute("href") != null)
                            {
                                deferredObject.Uri = link.Attribute("href").Value;
                            }
                            deferredObject.Deferred = true;

                            payloadObject.PayloadObjects.Add(deferredObject);
                        }
                    }
                    else if (linkRelValue.StartsWith(DataWebMediaResourceNamespace))
                    {
                        string             name        = linkRelValue.Substring(DataWebMediaResourceNamespace.Length);
                        PayloadNamedStream namedStream = payloadObject.NamedStreams.SingleOrDefault(s => s.Name == name);
                        if (namedStream == null)
                        {
                            namedStream = new PayloadNamedStream()
                            {
                                Name = name
                            };
                            payloadObject.NamedStreams.Add(namedStream);
                        }

                        UpdateNamedStreamMetadata(link, namedStream);
                        namedStream.SelfLink = link.Attribute("href").Value;
                    }
                    else if (linkRelValue.StartsWith(DataWebMediaResourceEditNamespace))
                    {
                        string             name        = linkRelValue.Substring(DataWebMediaResourceEditNamespace.Length);
                        PayloadNamedStream namedStream = payloadObject.NamedStreams.SingleOrDefault(s => s.Name == name);
                        if (namedStream == null)
                        {
                            namedStream = new PayloadNamedStream()
                            {
                                Name = name
                            };
                            payloadObject.NamedStreams.Add(namedStream);
                        }

                        UpdateNamedStreamMetadata(link, namedStream);
                        namedStream.EditLink = link.Attribute("href").Value;
                    }
                }
            }
            #endregion

            return(payloadObject);
        }