| /******************************************************************************* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| ******************************************************************************/ |
| package org.apache.olingo.odata2.core.ep.producer; |
| |
| import java.net.URI; |
| import java.net.URISyntaxException; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Date; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| |
| import javax.xml.stream.XMLStreamException; |
| import javax.xml.stream.XMLStreamWriter; |
| |
| import org.apache.olingo.odata2.api.ODataCallback; |
| import org.apache.olingo.odata2.api.edm.Edm; |
| import org.apache.olingo.odata2.api.edm.EdmCustomizableFeedMappings; |
| import org.apache.olingo.odata2.api.edm.EdmEntitySet; |
| import org.apache.olingo.odata2.api.edm.EdmException; |
| import org.apache.olingo.odata2.api.edm.EdmFacets; |
| import org.apache.olingo.odata2.api.edm.EdmLiteralKind; |
| import org.apache.olingo.odata2.api.edm.EdmMapping; |
| import org.apache.olingo.odata2.api.edm.EdmMultiplicity; |
| import org.apache.olingo.odata2.api.edm.EdmNavigationProperty; |
| import org.apache.olingo.odata2.api.edm.EdmSimpleType; |
| import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException; |
| import org.apache.olingo.odata2.api.edm.EdmTargetPath; |
| import org.apache.olingo.odata2.api.edm.EdmType; |
| import org.apache.olingo.odata2.api.ep.EntityProviderException; |
| import org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties; |
| import org.apache.olingo.odata2.api.ep.callback.OnWriteEntryContent; |
| import org.apache.olingo.odata2.api.ep.callback.OnWriteFeedContent; |
| import org.apache.olingo.odata2.api.ep.callback.WriteEntryCallbackContext; |
| import org.apache.olingo.odata2.api.ep.callback.WriteEntryCallbackResult; |
| import org.apache.olingo.odata2.api.ep.callback.WriteFeedCallbackContext; |
| import org.apache.olingo.odata2.api.ep.callback.WriteFeedCallbackResult; |
| import org.apache.olingo.odata2.api.exception.ODataApplicationException; |
| import org.apache.olingo.odata2.api.uri.ExpandSelectTreeNode; |
| import org.apache.olingo.odata2.core.commons.ContentType; |
| import org.apache.olingo.odata2.core.commons.Encoder; |
| import org.apache.olingo.odata2.core.edm.EdmDateTimeOffset; |
| import org.apache.olingo.odata2.core.ep.EntityProviderProducerException; |
| import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator; |
| import org.apache.olingo.odata2.core.ep.aggregator.EntityPropertyInfo; |
| import org.apache.olingo.odata2.core.ep.util.FormatXml; |
| |
| /** |
| * Serializes an ATOM entry. |
| * |
| */ |
| public class AtomEntryEntityProducer { |
| |
| private String etag; |
| private String location; |
| private final EntityProviderWriteProperties properties; |
| |
| public AtomEntryEntityProducer(final EntityProviderWriteProperties properties) throws EntityProviderException { |
| this.properties = properties == null ? EntityProviderWriteProperties.serviceRoot(null).build() : properties; |
| } |
| |
| public void append(final XMLStreamWriter writer, final EntityInfoAggregator eia, final Map<String, Object> data, |
| final boolean isRootElement, final boolean isFeedPart) throws EntityProviderException { |
| try { |
| writer.writeStartElement(FormatXml.ATOM_ENTRY); |
| |
| if (isRootElement) { |
| writer.writeDefaultNamespace(Edm.NAMESPACE_ATOM_2005); |
| writer.writeNamespace(Edm.PREFIX_M, Edm.NAMESPACE_M_2007_08); |
| writer.writeNamespace(Edm.PREFIX_D, Edm.NAMESPACE_D_2007_08); |
| } |
| if (!isFeedPart) { |
| writer.writeAttribute(Edm.PREFIX_XML, Edm.NAMESPACE_XML_1998, FormatXml.XML_BASE, properties.getServiceRoot() |
| .toASCIIString()); |
| } |
| |
| if (!properties.isContentOnly() && !properties.isOmitETag()) { |
| etag = createETag(eia, data); |
| if (etag != null) { |
| writer.writeAttribute(Edm.NAMESPACE_M_2007_08, FormatXml.M_ETAG, etag); |
| } |
| } |
| |
| String selfLink = null; |
| if (!properties.isContentOnly()) { |
| // write all atom infos (mandatory and optional) |
| selfLink = createSelfLink(eia, data, null); |
| appendAtomMandatoryParts(writer, eia, data, selfLink); |
| appendAtomOptionalParts(writer, eia, data); |
| } |
| if (eia.getEntityType().hasStream()) { |
| // write all links |
| if (!properties.isContentOnly()) { |
| appendAtomEditLink(writer, eia, selfLink); |
| appendAtomContentLink(writer, eia, data, selfLink); |
| appendAtomNavigationLinks(writer, eia, data); |
| } else { |
| appendAdditinalLinks(writer, eia, data); |
| } |
| // write properties/content |
| appendCustomProperties(writer, eia, data); |
| if (!properties.isContentOnly()) { |
| appendAtomContentPart(writer, eia, data, selfLink); |
| } |
| appendProperties(writer, eia, data); |
| } else { |
| // write all links |
| if (!properties.isContentOnly()) { |
| appendAtomEditLink(writer, eia, selfLink); |
| appendAtomNavigationLinks(writer, eia, data); |
| } else { |
| appendAdditinalLinks(writer, eia, data); |
| } |
| // write properties/content |
| appendCustomProperties(writer, eia, data); |
| writer.writeStartElement(FormatXml.ATOM_CONTENT); |
| writer.writeAttribute(FormatXml.ATOM_TYPE, ContentType.APPLICATION_XML.toString()); |
| appendProperties(writer, eia, data); |
| writer.writeEndElement(); |
| } |
| |
| writer.writeEndElement(); |
| |
| writer.flush(); |
| } catch (XMLStreamException e) { |
| throw new EntityProviderProducerException(EntityProviderException.COMMON, e); |
| } catch (EdmException e) { |
| throw new EntityProviderProducerException(e.getMessageReference(), e); |
| } catch (URISyntaxException e) { |
| throw new EntityProviderProducerException(EntityProviderException.COMMON, e); |
| } |
| } |
| |
| private void appendAdditinalLinks(final XMLStreamWriter writer, final EntityInfoAggregator eia, |
| final Map<String, Object> data) |
| throws EntityProviderException, EdmException, URISyntaxException { |
| final Map<String, Map<String, Object>> links = properties.getAdditionalLinks(); |
| if (links != null && !links.isEmpty()) { |
| for (Entry<String, Map<String, Object>> entry : links.entrySet()) { |
| Map<String, Object> navigationKeyMap = entry.getValue(); |
| final boolean isFeed = |
| (eia.getNavigationPropertyInfo(entry.getKey()).getMultiplicity() == EdmMultiplicity.MANY); |
| if (navigationKeyMap != null && !navigationKeyMap.isEmpty()) { |
| final EntityInfoAggregator targetEntityInfo = EntityInfoAggregator.create( |
| eia.getEntitySet().getRelatedEntitySet( |
| (EdmNavigationProperty) eia.getEntityType().getProperty(entry.getKey()))); |
| appendAtomNavigationLink(writer, createSelfLink(targetEntityInfo, navigationKeyMap, null), entry.getKey(), |
| isFeed, eia, data); |
| } |
| } |
| } |
| } |
| |
| private void appendCustomProperties(final XMLStreamWriter writer, final EntityInfoAggregator eia, |
| final Map<String, Object> data) throws EntityProviderException { |
| List<String> noneSyndicationTargetPaths = eia.getNoneSyndicationTargetPathNames(); |
| for (String tpName : noneSyndicationTargetPaths) { |
| EntityPropertyInfo info = eia.getTargetPathInfo(tpName); |
| final String name = info.getName(); |
| XmlPropertyEntityProducer aps = new XmlPropertyEntityProducer(properties); |
| aps.appendCustomProperty(writer, name, info, data.get(name)); |
| } |
| } |
| |
| protected static String createETag(final EntityInfoAggregator eia, final Map<String, Object> data) |
| throws EntityProviderException { |
| try { |
| String etag = null; |
| |
| Collection<EntityPropertyInfo> propertyInfos = eia.getETagPropertyInfos(); |
| for (EntityPropertyInfo propertyInfo : propertyInfos) { |
| EdmType edmType = propertyInfo.getType(); |
| if (edmType instanceof EdmSimpleType) { |
| EdmSimpleType edmSimpleType = (EdmSimpleType) edmType; |
| if (etag == null) { |
| etag = |
| edmSimpleType.valueToString(data.get(propertyInfo.getName()), EdmLiteralKind.DEFAULT, propertyInfo |
| .getFacets()); |
| } else { |
| etag = |
| etag |
| + Edm.DELIMITER |
| + edmSimpleType.valueToString(data.get(propertyInfo.getName()), EdmLiteralKind.DEFAULT, |
| propertyInfo.getFacets()); |
| } |
| } |
| } |
| |
| if (etag != null) { |
| etag = "W/\"" + etag + "\""; |
| } |
| |
| return etag; |
| } catch (EdmSimpleTypeException e) { |
| throw new EntityProviderProducerException(e.getMessageReference(), e); |
| } |
| } |
| |
| private void appendAtomNavigationLinks(final XMLStreamWriter writer, final EntityInfoAggregator eia, |
| final Map<String, Object> data) throws EntityProviderException, EdmException, URISyntaxException { |
| for (String name : eia.getSelectedNavigationPropertyNames()) { |
| final boolean isFeed = (eia.getNavigationPropertyInfo(name).getMultiplicity() == EdmMultiplicity.MANY); |
| final Map<String, Map<String, Object>> links = properties.getAdditionalLinks(); |
| final Map<String, Object> key = links == null ? null : links.get(name); |
| if (key == null || key.isEmpty()) { |
| appendAtomNavigationLink(writer, createSelfLink(eia, data, name), name, isFeed, eia, data); |
| } else { |
| final EntityInfoAggregator targetEntityInfo = EntityInfoAggregator.create( |
| eia.getEntitySet().getRelatedEntitySet((EdmNavigationProperty) eia.getEntityType().getProperty(name))); |
| appendAtomNavigationLink(writer, createSelfLink(targetEntityInfo, key, null), name, isFeed, eia, data); |
| } |
| } |
| } |
| |
| private void appendAtomNavigationLink(final XMLStreamWriter writer, final String target, |
| final String navigationPropertyName, final boolean isFeed, final EntityInfoAggregator eia, |
| final Map<String, Object> data) throws EntityProviderException, EdmException, URISyntaxException { |
| try { |
| writer.writeStartElement(FormatXml.ATOM_LINK); |
| writer.writeAttribute(FormatXml.ATOM_HREF, target); |
| writer.writeAttribute(FormatXml.ATOM_REL, Edm.NAMESPACE_REL_2007_08 + navigationPropertyName); |
| writer.writeAttribute(FormatXml.ATOM_TITLE, navigationPropertyName); |
| if (isFeed) { |
| writer.writeAttribute(FormatXml.ATOM_TYPE, ContentType.APPLICATION_ATOM_XML_FEED.toString()); |
| appendInlineFeed(writer, navigationPropertyName, eia, data, target); |
| } else { |
| writer.writeAttribute(FormatXml.ATOM_TYPE, ContentType.APPLICATION_ATOM_XML_ENTRY.toString()); |
| appendInlineEntry(writer, navigationPropertyName, eia, data); |
| } |
| writer.writeEndElement(); |
| } catch (XMLStreamException e) { |
| throw new EntityProviderProducerException(EntityProviderException.COMMON, e); |
| } |
| } |
| |
| private void appendInlineFeed(final XMLStreamWriter writer, final String navigationPropertyName, |
| final EntityInfoAggregator eia, final Map<String, Object> data, final String self) |
| throws EntityProviderException, XMLStreamException, EdmException, URISyntaxException { |
| |
| if (eia.getExpandedNavigationPropertyNames().contains(navigationPropertyName)) { |
| if (properties.getCallbacks() != null && properties.getCallbacks().containsKey(navigationPropertyName)) { |
| writer.writeStartElement(Edm.NAMESPACE_M_2007_08, FormatXml.M_INLINE); |
| |
| EdmNavigationProperty navProp = (EdmNavigationProperty) eia.getEntityType().getProperty(navigationPropertyName); |
| WriteFeedCallbackContext context = new WriteFeedCallbackContext(); |
| context.setSourceEntitySet(eia.getEntitySet()); |
| context.setNavigationProperty(navProp); |
| context.setEntryData(data); |
| context.setCurrentWriteProperties(properties); |
| ExpandSelectTreeNode subNode = properties.getExpandSelectTree().getLinks().get(navigationPropertyName); |
| context.setCurrentExpandSelectTreeNode(subNode); |
| context.setSelfLink(new URI(self)); |
| |
| ODataCallback callback = properties.getCallbacks().get(navigationPropertyName); |
| if (callback == null) { |
| throw new EntityProviderProducerException(EntityProviderException.EXPANDNOTSUPPORTED); |
| } |
| WriteFeedCallbackResult result; |
| try { |
| result = ((OnWriteFeedContent) callback).retrieveFeedResult(context); |
| } catch (ODataApplicationException e) { |
| throw new EntityProviderProducerException(EntityProviderException.COMMON, e); |
| } |
| List<Map<String, Object>> inlineData = result.getFeedData(); |
| if (inlineData == null) { |
| inlineData = new ArrayList<Map<String, Object>>(); |
| } |
| |
| EntityProviderWriteProperties inlineProperties = result.getInlineProperties(); |
| EdmEntitySet inlineEntitySet = eia.getEntitySet().getRelatedEntitySet(navProp); |
| AtomFeedProducer inlineFeedProducer = new AtomFeedProducer(inlineProperties); |
| EntityInfoAggregator inlineEia = |
| EntityInfoAggregator.create(inlineEntitySet, inlineProperties.getExpandSelectTree()); |
| inlineFeedProducer.append(writer, inlineEia, inlineData, true); |
| |
| writer.writeEndElement(); |
| } |
| } |
| } |
| |
| private void appendInlineEntry(final XMLStreamWriter writer, final String navigationPropertyName, |
| final EntityInfoAggregator eia, final Map<String, Object> data) throws EntityProviderException, |
| XMLStreamException, EdmException { |
| |
| if (eia.getExpandedNavigationPropertyNames().contains(navigationPropertyName)) { |
| if (properties.getCallbacks() != null && properties.getCallbacks().containsKey(navigationPropertyName)) { |
| writer.writeStartElement(Edm.NAMESPACE_M_2007_08, FormatXml.M_INLINE); |
| |
| EdmNavigationProperty navProp = (EdmNavigationProperty) eia.getEntityType().getProperty(navigationPropertyName); |
| WriteEntryCallbackContext context = new WriteEntryCallbackContext(); |
| context.setSourceEntitySet(eia.getEntitySet()); |
| context.setCurrentWriteProperties(properties); |
| context.setNavigationProperty(navProp); |
| context.setEntryData(data); |
| ExpandSelectTreeNode subNode = properties.getExpandSelectTree().getLinks().get(navigationPropertyName); |
| context.setCurrentExpandSelectTreeNode(subNode); |
| |
| ODataCallback callback = properties.getCallbacks().get(navigationPropertyName); |
| if (callback == null) { |
| throw new EntityProviderProducerException(EntityProviderException.EXPANDNOTSUPPORTED); |
| } |
| WriteEntryCallbackResult result; |
| try { |
| result = ((OnWriteEntryContent) callback).retrieveEntryResult(context); |
| } catch (ODataApplicationException e) { |
| throw new EntityProviderProducerException(EntityProviderException.COMMON, e); |
| } |
| Map<String, Object> inlineData = result.getEntryData(); |
| if (inlineData != null && !inlineData.isEmpty()) { |
| EntityProviderWriteProperties inlineProperties = result.getInlineProperties(); |
| EdmEntitySet inlineEntitySet = eia.getEntitySet().getRelatedEntitySet(navProp); |
| AtomEntryEntityProducer inlineProducer = new AtomEntryEntityProducer(inlineProperties); |
| EntityInfoAggregator inlineEia = |
| EntityInfoAggregator.create(inlineEntitySet, inlineProperties.getExpandSelectTree()); |
| inlineProducer.append(writer, inlineEia, inlineData, false, false); |
| } |
| |
| writer.writeEndElement(); |
| } |
| } |
| |
| } |
| |
| private void appendAtomEditLink(final XMLStreamWriter writer, final EntityInfoAggregator eia, |
| final String selfLink) throws EntityProviderException { |
| try { |
| writer.writeStartElement(FormatXml.ATOM_LINK); |
| writer.writeAttribute(FormatXml.ATOM_HREF, selfLink); |
| writer.writeAttribute(FormatXml.ATOM_REL, Edm.LINK_REL_EDIT); |
| writer.writeAttribute(FormatXml.ATOM_TITLE, eia.getEntityType().getName()); |
| writer.writeEndElement(); |
| } catch (XMLStreamException e) { |
| throw new EntityProviderProducerException(EntityProviderException.COMMON, e); |
| } catch (EdmException e) { |
| throw new EntityProviderProducerException(e.getMessageReference(), e); |
| } |
| } |
| |
| private void appendAtomContentLink(final XMLStreamWriter writer, final EntityInfoAggregator eia, |
| final Map<String, Object> data, final String selfLink) throws EntityProviderException, EdmException { |
| try { |
| String mediaResourceMimeType = null; |
| EdmMapping entityTypeMapping = eia.getEntityType().getMapping(); |
| if (entityTypeMapping != null) { |
| String mediaResourceMimeTypeKey = entityTypeMapping.getMediaResourceMimeTypeKey(); |
| if (mediaResourceMimeTypeKey != null) { |
| mediaResourceMimeType = (String) data.get(mediaResourceMimeTypeKey); |
| } |
| } |
| if (mediaResourceMimeType == null) { |
| mediaResourceMimeType = ContentType.APPLICATION_OCTET_STREAM.toString(); |
| } |
| |
| writer.writeStartElement(FormatXml.ATOM_LINK); |
| writer.writeAttribute(FormatXml.ATOM_HREF, selfLink + "/$value"); |
| writer.writeAttribute(FormatXml.ATOM_REL, Edm.LINK_REL_EDIT_MEDIA); |
| writer.writeAttribute(FormatXml.ATOM_TYPE, mediaResourceMimeType); |
| writer.writeEndElement(); |
| } catch (XMLStreamException e) { |
| throw new EntityProviderProducerException(EntityProviderException.COMMON, e); |
| } |
| } |
| |
| private void appendAtomContentPart(final XMLStreamWriter writer, final EntityInfoAggregator eia, |
| final Map<String, Object> data, final String selfLink) throws EntityProviderException, EdmException { |
| try { |
| |
| EdmMapping entityTypeMapping = eia.getEntityType().getMapping(); |
| String self = null; |
| String mediaResourceMimeType = null; |
| |
| if (entityTypeMapping != null) { |
| String mediaResourceSourceKey = entityTypeMapping.getMediaResourceSourceKey(); |
| if (mediaResourceSourceKey != null) { |
| self = (String) data.get(mediaResourceSourceKey); |
| } |
| if (self == null) { |
| self = selfLink + "/$value"; |
| } |
| String mediaResourceMimeTypeKey = entityTypeMapping.getMediaResourceMimeTypeKey(); |
| if (mediaResourceMimeTypeKey != null) { |
| mediaResourceMimeType = (String) data.get(mediaResourceMimeTypeKey); |
| } |
| if (mediaResourceMimeType == null) { |
| mediaResourceMimeType = ContentType.APPLICATION_OCTET_STREAM.toString(); |
| } |
| } else { |
| self = selfLink + "/$value"; |
| mediaResourceMimeType = ContentType.APPLICATION_OCTET_STREAM.toString(); |
| } |
| |
| writer.writeEmptyElement(FormatXml.ATOM_CONTENT); |
| writer.writeAttribute(FormatXml.ATOM_TYPE, mediaResourceMimeType); |
| writer.writeAttribute(FormatXml.ATOM_SRC, self); |
| } catch (XMLStreamException e) { |
| throw new EntityProviderProducerException(EntityProviderException.COMMON, e); |
| } |
| } |
| |
| private void appendAtomMandatoryParts(final XMLStreamWriter writer, final EntityInfoAggregator eia, |
| final Map<String, Object> data, final String selfLink) throws EntityProviderException { |
| try { |
| writer.writeStartElement(FormatXml.ATOM_ID); |
| location = properties.getServiceRoot().toASCIIString() + selfLink; |
| writer.writeCharacters(location); |
| writer.writeEndElement(); |
| |
| writer.writeStartElement(FormatXml.ATOM_TITLE); |
| writer.writeAttribute(FormatXml.ATOM_TYPE, FormatXml.ATOM_TEXT); |
| EntityPropertyInfo titleInfo = eia.getTargetPathInfo(EdmTargetPath.SYNDICATION_TITLE); |
| if (titleInfo != null) { |
| EdmSimpleType st = (EdmSimpleType) titleInfo.getType(); |
| Object object = data.get(titleInfo.getName()); |
| String title = st.valueToString(object, EdmLiteralKind.DEFAULT, titleInfo.getFacets()); |
| if (title != null) { |
| writer.writeCharacters(title); |
| } |
| } else { |
| writer.writeCharacters(eia.getEntitySetName()); |
| } |
| writer.writeEndElement(); |
| |
| writer.writeStartElement(FormatXml.ATOM_UPDATED); |
| |
| writer.writeCharacters(getUpdatedString(eia, data)); |
| |
| writer.writeEndElement(); |
| } catch (XMLStreamException e) { |
| throw new EntityProviderProducerException(EntityProviderException.COMMON, e); |
| } catch (EdmSimpleTypeException e) { |
| throw new EntityProviderProducerException(e.getMessageReference(), e); |
| } |
| } |
| |
| String getUpdatedString(final EntityInfoAggregator eia, final Map<String, Object> data) |
| throws EdmSimpleTypeException { |
| Object updateDate = null; |
| EdmFacets updateFacets = null; |
| EntityPropertyInfo updatedInfo = eia.getTargetPathInfo(EdmTargetPath.SYNDICATION_UPDATED); |
| if (updatedInfo != null) { |
| updateDate = data.get(updatedInfo.getName()); |
| if (updateDate != null) { |
| updateFacets = updatedInfo.getFacets(); |
| } |
| } |
| if (updateDate == null) { |
| updateDate = new Date(); |
| } |
| return EdmDateTimeOffset.getInstance().valueToString(updateDate, EdmLiteralKind.DEFAULT, updateFacets); |
| } |
| |
| private String getTargetPathValue(final EntityInfoAggregator eia, final String targetPath, |
| final Map<String, Object> data) throws EntityProviderException { |
| try { |
| EntityPropertyInfo info = eia.getTargetPathInfo(targetPath); |
| if (info != null) { |
| EdmSimpleType type = (EdmSimpleType) info.getType(); |
| Object value = data.get(info.getName()); |
| return type.valueToString(value, EdmLiteralKind.DEFAULT, info.getFacets()); |
| } |
| return null; |
| } catch (EdmSimpleTypeException e) { |
| throw new EntityProviderProducerException(e.getMessageReference(), e); |
| } |
| } |
| |
| private void appendAtomOptionalParts(final XMLStreamWriter writer, final EntityInfoAggregator eia, |
| final Map<String, Object> data) throws EntityProviderException { |
| try { |
| String authorEmail = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_AUTHOREMAIL, data); |
| String authorName = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_AUTHORNAME, data); |
| String authorUri = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_AUTHORURI, data); |
| if (authorEmail != null || authorName != null || authorUri != null) { |
| writer.writeStartElement(FormatXml.ATOM_AUTHOR); |
| appendAtomOptionalPart(writer, FormatXml.ATOM_AUTHOR_NAME, authorName, false); |
| appendAtomOptionalPart(writer, FormatXml.ATOM_AUTHOR_EMAIL, authorEmail, false); |
| appendAtomOptionalPart(writer, FormatXml.ATOM_AUTHOR_URI, authorUri, false); |
| writer.writeEndElement(); |
| } |
| |
| String summary = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_SUMMARY, data); |
| appendAtomOptionalPart(writer, FormatXml.ATOM_SUMMARY, summary, true); |
| |
| String contributorName = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_CONTRIBUTORNAME, data); |
| String contributorEmail = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_CONTRIBUTOREMAIL, data); |
| String contributorUri = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_CONTRIBUTORURI, data); |
| if (contributorEmail != null || contributorName != null || contributorUri != null) { |
| writer.writeStartElement(FormatXml.ATOM_CONTRIBUTOR); |
| appendAtomOptionalPart(writer, FormatXml.ATOM_CONTRIBUTOR_NAME, contributorName, false); |
| appendAtomOptionalPart(writer, FormatXml.ATOM_CONTRIBUTOR_EMAIL, contributorEmail, false); |
| appendAtomOptionalPart(writer, FormatXml.ATOM_CONTRIBUTOR_URI, contributorUri, false); |
| writer.writeEndElement(); |
| } |
| |
| String rights = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_RIGHTS, data); |
| appendAtomOptionalPart(writer, FormatXml.ATOM_RIGHTS, rights, true); |
| String published = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_PUBLISHED, data); |
| appendAtomOptionalPart(writer, FormatXml.ATOM_PUBLISHED, published, false); |
| |
| String term = eia.getEntityType().getNamespace() + Edm.DELIMITER + eia.getEntityType().getName(); |
| writer.writeStartElement(FormatXml.ATOM_CATEGORY); |
| writer.writeAttribute(FormatXml.ATOM_CATEGORY_TERM, term); |
| writer.writeAttribute(FormatXml.ATOM_CATEGORY_SCHEME, Edm.NAMESPACE_SCHEME_2007_08); |
| writer.writeEndElement(); |
| } catch (XMLStreamException e) { |
| throw new EntityProviderProducerException(EntityProviderException.COMMON, e); |
| } catch (EdmException e) { |
| throw new EntityProviderProducerException(e.getMessageReference(), e); |
| } |
| } |
| |
| private void appendAtomOptionalPart(final XMLStreamWriter writer, final String name, final String value, |
| final boolean writeType) throws EntityProviderException { |
| try { |
| if (value != null) { |
| writer.writeStartElement(name); |
| if (writeType) { |
| writer.writeAttribute(FormatXml.ATOM_TYPE, FormatXml.ATOM_TEXT); |
| } |
| writer.writeCharacters(value); |
| writer.writeEndElement(); |
| } |
| } catch (XMLStreamException e) { |
| throw new EntityProviderProducerException(EntityProviderException.COMMON, e); |
| } |
| } |
| |
| static String createSelfLink(final EntityInfoAggregator eia, final Map<String, Object> data, final String extension) |
| throws EntityProviderException { |
| StringBuilder sb = new StringBuilder(); |
| if (!eia.isDefaultEntityContainer()) { |
| sb.append(Encoder.encode(eia.getEntityContainerName())).append(Edm.DELIMITER); |
| } |
| sb.append(Encoder.encode(eia.getEntitySetName())); |
| |
| sb.append("(").append(createEntryKey(eia, data)).append(")").append(extension == null ? "" : ("/" + extension)); |
| return sb.toString(); |
| } |
| |
| private static String createEntryKey(final EntityInfoAggregator entityInfo, final Map<String, Object> data) |
| throws EntityProviderException { |
| final List<EntityPropertyInfo> keyPropertyInfos = entityInfo.getKeyPropertyInfos(); |
| |
| StringBuilder keys = new StringBuilder(); |
| for (final EntityPropertyInfo keyPropertyInfo : keyPropertyInfos) { |
| if (keys.length() > 0) { |
| keys.append(','); |
| } |
| |
| final String name = keyPropertyInfo.getName(); |
| if (keyPropertyInfos.size() > 1) { |
| keys.append(Encoder.encode(name)).append('='); |
| } |
| |
| final EdmSimpleType type = (EdmSimpleType) keyPropertyInfo.getType(); |
| try { |
| keys.append(Encoder.encode(type.valueToString(data.get(name), EdmLiteralKind.URI, |
| keyPropertyInfo.getFacets()))); |
| } catch (final EdmSimpleTypeException e) { |
| throw new EntityProviderProducerException(e.getMessageReference(), e); |
| } |
| } |
| |
| return keys.toString(); |
| } |
| |
| private void appendProperties(final XMLStreamWriter writer, final EntityInfoAggregator eia, |
| final Map<String, Object> data) throws EntityProviderException { |
| try { |
| if (properties.isDataBasedPropertySerialization()) { |
| if (!data.isEmpty()) { |
| writer.writeStartElement(Edm.NAMESPACE_M_2007_08, FormatXml.M_PROPERTIES); |
| for (String propertyName : eia.getPropertyNames()) { |
| if (data.containsKey(propertyName)) { |
| appendPropertyNameValue(writer, eia, data, propertyName); |
| } |
| } |
| writer.writeEndElement(); |
| } |
| } else { |
| List<String> propertyNames = eia.getSelectedPropertyNames(); |
| if (!propertyNames.isEmpty()) { |
| writer.writeStartElement(Edm.NAMESPACE_M_2007_08, FormatXml.M_PROPERTIES); |
| |
| for (String propertyName : propertyNames) { |
| appendPropertyNameValue(writer, eia, data, propertyName); |
| } |
| writer.writeEndElement(); |
| } |
| } |
| } catch (XMLStreamException e) { |
| throw new EntityProviderProducerException(EntityProviderException.COMMON, e); |
| } |
| } |
| |
| /** |
| * @param writer |
| * @param eia |
| * @param data |
| * @param propertyName |
| * @throws EntityProviderException |
| */ |
| private void appendPropertyNameValue(final XMLStreamWriter writer, final EntityInfoAggregator eia, |
| final Map<String, Object> data, String propertyName) throws EntityProviderException { |
| EntityPropertyInfo propertyInfo = eia.getPropertyInfo(propertyName); |
| if (isNotMappedViaCustomMapping(propertyInfo)) { |
| Object value = data.get(propertyName); |
| XmlPropertyEntityProducer aps = new XmlPropertyEntityProducer(properties); |
| aps.append(writer, propertyInfo.getName(), propertyInfo, value); |
| } |
| } |
| |
| private boolean isNotMappedViaCustomMapping(final EntityPropertyInfo propertyInfo) { |
| EdmCustomizableFeedMappings customMapping = propertyInfo.getCustomMapping(); |
| if (customMapping != null && customMapping.isFcKeepInContent() != null) { |
| return customMapping.isFcKeepInContent(); |
| } |
| return true; |
| } |
| |
| public String getETag() { |
| return etag; |
| } |
| |
| public String getLocation() { |
| return location; |
| } |
| } |