You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by il...@apache.org on 2014/03/24 10:42:36 UTC
[47/50] [abbrv] git commit: [OLINGO-205,
OLINGO-200] provided atom v4 deserialization for entity type/set +
entity set request
[OLINGO-205, OLINGO-200] provided atom v4 deserialization for entity type/set + entity set request
Project: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/commit/9aefb959
Tree: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/tree/9aefb959
Diff: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/diff/9aefb959
Branch: refs/heads/master
Commit: 9aefb95905edee86a6747c26afa40d6f57451008
Parents: 4780fc5
Author: fmartelli <fa...@gmail.com>
Authored: Mon Mar 24 09:50:23 2014 +0100
Committer: fmartelli <fa...@gmail.com>
Committed: Mon Mar 24 09:50:23 2014 +0100
----------------------------------------------------------------------
.../org/apache/olingo/fit/AbstractServices.java | 28 +-
.../olingo/fit/utils/AbstractJSONUtilities.java | 503 +++++++
.../olingo/fit/utils/AbstractUtilities.java | 3 +-
.../olingo/fit/utils/AbstractXMLUtilities.java | 1302 ++++++++++++++++
.../org/apache/olingo/fit/utils/Accept.java | 50 +-
.../org/apache/olingo/fit/utils/Commons.java | 6 +-
.../apache/olingo/fit/utils/JSONUtilities.java | 503 -------
.../apache/olingo/fit/utils/XMLUtilities.java | 1388 ------------------
.../olingo/fit/utils/v3/JSONUtilities.java | 28 +
.../olingo/fit/utils/v3/XMLUtilities.java | 191 +++
.../olingo/fit/utils/v4/JSONUtilities.java | 28 +
.../olingo/fit/utils/v4/XMLUtilities.java | 142 ++
fit/src/main/resources/v4/People/feed.full.json | 332 +++++
fit/src/main/resources/v4/People/feed.xml | 218 +++
fit/src/main/resources/v4/metadata.xml | 743 +++++-----
.../request/ODataBasicRequest.java | 3 +-
.../request/retrieve/ODataRetrieveRequest.java | 3 +-
.../olingo/client/api/domain/ODataLinkType.java | 8 +-
.../apache/olingo/client/api/format/Format.java | 26 +
.../olingo/client/api/format/ODataFormat.java | 8 +-
.../client/api/format/ODataMediaFormat.java | 8 +-
.../client/api/format/ODataPubFormat.java | 47 +-
.../client/api/format/ODataValueFormat.java | 8 +-
.../request/AbstractODataBasicRequest.java | 144 +-
.../communication/request/ODataRequestImpl.java | 12 +-
.../request/invoke/ODataInvokeRequestImpl.java | 4 +-
.../retrieve/AbstractODataRetrieveRequest.java | 3 +-
.../request/retrieve/ODataRawRequestImpl.java | 2 +-
.../AbstractODataStreamedEntityRequest.java | 4 +-
.../core/data/AbstractJsonDeserializer.java | 5 +-
.../client/core/data/AtomDeserializer.java | 2 -
.../core/data/AtomPropertyDeserializer.java | 16 +-
.../core/data/JSONGeoValueDeserializer.java | 11 +-
.../client/core/edm/EdmActionImportImpl.java | 1 -
.../client/core/edm/EdmOperationImpl.java | 8 +-
.../olingo/client/core/edm/EdmTypeInfo.java | 26 +-
.../core/op/impl/AbstractODataBinder.java | 8 +-
.../core/op/impl/AbstractODataDeserializer.java | 1 -
.../core/it/v3/EntityRetrieveTestITCase.java | 2 +-
.../client/core/it/v3/EntitySetTestITCase.java | 2 +-
.../core/it/v3/QueryOptionsTestITCase.java | 3 +-
.../client/core/it/v4/AbstractTestITCase.java | 4 +-
.../client/core/it/v4/EntitySetTestITCase.java | 152 ++
.../org/apache/olingo/commons/api/edm/Edm.java | 161 +-
.../olingo/commons/api/edm/EdmActionImport.java | 2 +-
.../api/edm/constants/ODataServiceVersion.java | 7 +-
.../core/edm/AbstractEdmComplexType.java | 39 +-
.../core/edm/AbstractEdmEntityContainer.java | 176 +--
.../commons/core/edm/AbstractEdmOperation.java | 131 +-
.../core/edm/AbstractEdmOperationImport.java | 65 +-
.../core/edm/AbstractEdmStructuredType.java | 159 +-
.../olingo/commons/core/edm/EdmNamedImpl.java | 21 +-
.../olingo/commons/core/edm/EdmTypeImpl.java | 31 +-
53 files changed, 3917 insertions(+), 2861 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/9aefb959/fit/src/main/java/org/apache/olingo/fit/AbstractServices.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/AbstractServices.java b/fit/src/main/java/org/apache/olingo/fit/AbstractServices.java
index 12032c5..025e4fe 100644
--- a/fit/src/main/java/org/apache/olingo/fit/AbstractServices.java
+++ b/fit/src/main/java/org/apache/olingo/fit/AbstractServices.java
@@ -19,8 +19,8 @@
package org.apache.olingo.fit;
import org.apache.olingo.fit.utils.Accept;
-import org.apache.olingo.fit.utils.XMLUtilities;
-import org.apache.olingo.fit.utils.JSONUtilities;
+import org.apache.olingo.fit.utils.AbstractXMLUtilities;
+import org.apache.olingo.fit.utils.AbstractJSONUtilities;
import org.apache.olingo.fit.utils.ODataVersion;
import org.apache.olingo.fit.utils.FSManager;
@@ -70,13 +70,18 @@ public abstract class AbstractServices {
private static Set<ODataVersion> initialized = EnumSet.noneOf(ODataVersion.class);
protected abstract ODataVersion getVersion();
- protected final XMLUtilities xml;
+ protected final AbstractXMLUtilities xml;
- protected final JSONUtilities json;
+ protected final AbstractJSONUtilities json;
public AbstractServices() throws Exception {
- this.xml = new XMLUtilities(getVersion());
- this.json = new JSONUtilities(getVersion());
+ if (ODataVersion.v3 == getVersion()) {
+ this.xml = new org.apache.olingo.fit.utils.v3.XMLUtilities();
+ this.json = new org.apache.olingo.fit.utils.v3.JSONUtilities();
+ } else {
+ this.xml = new org.apache.olingo.fit.utils.v4.XMLUtilities();
+ this.json = new org.apache.olingo.fit.utils.v4.JSONUtilities();
+ }
if (!initialized.contains(getVersion())) {
xml.retrieveLinkInfoFromMetadata();
@@ -135,7 +140,7 @@ public abstract class AbstractServices {
return xml.
createResponse(FSManager.instance(getVersion()).readFile(filename, Accept.XML), null, Accept.XML);
} catch (Exception e) {
- return xml.createFaultResponse(Accept.XML.toString(), e);
+ return xml.createFaultResponse(Accept.XML.toString(getVersion()), e);
}
}
@@ -547,7 +552,7 @@ public abstract class AbstractServices {
return xml.createResponse(null, null, null, Response.Status.NO_CONTENT);
} catch (Exception e) {
- return xml.createFaultResponse(Accept.XML.toString(), e);
+ return xml.createFaultResponse(Accept.XML.toString(getVersion()), e);
}
}
@@ -749,7 +754,7 @@ public abstract class AbstractServices {
} catch (Exception e) {
LOG.error("Error retrieving entity", e);
- return xml.createFaultResponse(Accept.JSON.toString(), e);
+ return xml.createFaultResponse(Accept.JSON.toString(getVersion()), e);
}
}
@@ -775,7 +780,7 @@ public abstract class AbstractServices {
@QueryParam("$format") @DefaultValue(StringUtils.EMPTY) String format,
final String changes) {
if (xml.isMediaContent(entitySetName + "/" + path)) {
- return replaceMediaProperty(prefer, entitySetName, entityId, path, format, changes);
+ return replaceMediaProperty(prefer, entitySetName, entityId, path, changes);
} else {
return replaceProperty(accept, prefer, entitySetName, entityId, path, format, changes, false);
}
@@ -786,7 +791,6 @@ public abstract class AbstractServices {
final String entitySetName,
final String entityId,
final String path,
- final String format,
final String value) {
try {
final AbstractUtilities utils = getUtilities(null);
@@ -809,7 +813,7 @@ public abstract class AbstractServices {
} catch (Exception e) {
LOG.error("Error retrieving entity", e);
- return xml.createFaultResponse(Accept.JSON.toString(), e);
+ return xml.createFaultResponse(Accept.JSON.toString(getVersion()), e);
}
}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/9aefb959/fit/src/main/java/org/apache/olingo/fit/utils/AbstractJSONUtilities.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/utils/AbstractJSONUtilities.java b/fit/src/main/java/org/apache/olingo/fit/utils/AbstractJSONUtilities.java
new file mode 100644
index 0000000..c62d341
--- /dev/null
+++ b/fit/src/main/java/org/apache/olingo/fit/utils/AbstractJSONUtilities.java
@@ -0,0 +1,503 @@
+/*
+ * 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.fit.utils;
+
+import static org.apache.olingo.fit.utils.Constants.*;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.fasterxml.jackson.databind.node.TextNode;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.util.AbstractMap.SimpleEntry;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.ws.rs.NotFoundException;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
+
+public abstract class AbstractJSONUtilities extends AbstractUtilities {
+
+ public AbstractJSONUtilities(final ODataVersion version) throws Exception {
+ super(version);
+ }
+
+ @Override
+ protected Accept getDefaultFormat() {
+ return Accept.JSON_FULLMETA;
+ }
+
+ @Override
+ protected InputStream addLinks(
+ final String entitySetName, final String entitykey, final InputStream is, final Set<String> links)
+ throws Exception {
+ final ObjectMapper mapper = new ObjectMapper();
+ final ObjectNode srcNode = (ObjectNode) mapper.readTree(is);
+ IOUtils.closeQuietly(is);
+
+ for (String link : links) {
+ srcNode.set(link + JSON_NAVIGATION_SUFFIX,
+ new TextNode(Commons.getLinksURI(version, entitySetName, entitykey, link)));
+ }
+
+ return IOUtils.toInputStream(srcNode.toString());
+ }
+
+ @Override
+ protected Set<String> retrieveAllLinkNames(InputStream is) throws Exception {
+ final ObjectMapper mapper = new ObjectMapper();
+ final ObjectNode srcNode = (ObjectNode) mapper.readTree(is);
+ IOUtils.closeQuietly(is);
+
+ final Set<String> links = new HashSet<String>();
+
+ final Iterator<String> fieldIter = srcNode.fieldNames();
+
+ while (fieldIter.hasNext()) {
+ final String field = fieldIter.next();
+
+ if (field.endsWith(JSON_NAVIGATION_BIND_SUFFIX)
+ || field.endsWith(JSON_NAVIGATION_SUFFIX)
+ || field.endsWith(JSON_MEDIA_SUFFIX)
+ || field.endsWith(JSON_EDITLINK_NAME)) {
+ if (field.indexOf('@') > 0) {
+ links.add(field.substring(0, field.indexOf('@')));
+ } else {
+ links.add(field);
+ }
+ }
+ }
+
+ return links;
+ }
+
+ /**
+ * {@inheritDoc }
+ */
+ @Override
+ protected NavigationLinks retrieveNavigationInfo(
+ final String entitySetName, final InputStream is)
+ throws Exception {
+ final ObjectMapper mapper = new ObjectMapper();
+ final ObjectNode srcNode = (ObjectNode) mapper.readTree(is);
+ IOUtils.closeQuietly(is);
+
+ final NavigationLinks links = new NavigationLinks();
+
+ final Iterator<Map.Entry<String, JsonNode>> fieldIter = srcNode.fields();
+
+ while (fieldIter.hasNext()) {
+ final Map.Entry<String, JsonNode> field = fieldIter.next();
+ if (field.getKey().endsWith(JSON_NAVIGATION_BIND_SUFFIX)) {
+ final String title = field.getKey().substring(0, field.getKey().indexOf('@'));
+ final List<String> hrefs = new ArrayList<String>();
+ if (field.getValue().isArray()) {
+ for (JsonNode href : ((ArrayNode) field.getValue())) {
+ final String uri = href.asText();
+ hrefs.add(uri.substring(uri.lastIndexOf('/') + 1));
+ }
+ } else {
+ final String uri = field.getValue().asText();
+ hrefs.add(uri.substring(uri.lastIndexOf('/') + 1));
+ }
+
+ links.addLinks(title, hrefs);
+ } else if (Commons.linkInfo.get(version).exists(entitySetName, field.getKey())) {
+ links.addInlines(field.getKey(), IOUtils.toInputStream(field.getValue().toString()));
+ }
+ }
+
+ return links;
+ }
+
+ /**
+ * {@inheritDoc }
+ */
+ @Override
+ protected InputStream normalizeLinks(
+ final String entitySetName, final String entityKey, final InputStream is, final NavigationLinks links)
+ throws Exception {
+ final ObjectMapper mapper = new ObjectMapper();
+ final ObjectNode srcNode = (ObjectNode) mapper.readTree(is);
+
+ if (links != null) {
+ for (String linkTitle : links.getLinkNames()) {
+ // normalize link
+ srcNode.remove(linkTitle + JSON_NAVIGATION_BIND_SUFFIX);
+ srcNode.set(
+ linkTitle + JSON_NAVIGATION_SUFFIX,
+ new TextNode(String.format("%s(%s)/%s", entitySetName, entityKey, linkTitle)));
+ }
+
+ for (String linkTitle : links.getInlineNames()) {
+ // normalize link if exist; declare a new one if missing
+ srcNode.remove(linkTitle + JSON_NAVIGATION_BIND_SUFFIX);
+ srcNode.set(
+ linkTitle + JSON_NAVIGATION_SUFFIX,
+ new TextNode(String.format("%s(%s)/%s", entitySetName, entityKey, linkTitle)));
+
+ // remove inline
+ srcNode.remove(linkTitle);
+
+ // remove from links
+ links.removeLink(linkTitle);
+ }
+ }
+
+ srcNode.set(
+ JSON_EDITLINK_NAME,
+ new TextNode(Constants.DEFAULT_SERVICE_URL + entitySetName + "(" + entityKey + ")"));
+
+ return IOUtils.toInputStream(srcNode.toString());
+ }
+
+ @Override
+ public InputStream getPropertyValue(final InputStream src, final List<String> path)
+ throws Exception {
+ final ObjectMapper mapper = new ObjectMapper();
+ final JsonNode srcNode = mapper.readTree(src);
+ JsonNode node = getProperty(srcNode, path);
+ return IOUtils.toInputStream(node.asText());
+ }
+
+ @Override
+ public InputStream getProperty(
+ final String entitySetName, final String entityId, final List<String> path, final String edmType)
+ throws Exception {
+
+ final InputStream src =
+ fsManager.readFile(Commons.getEntityBasePath(entitySetName, entityId) + ENTITY, Accept.JSON_FULLMETA);
+
+ final ObjectMapper mapper = new ObjectMapper();
+ final JsonNode srcNode = mapper.readTree(src);
+
+ final ObjectNode propertyNode = new ObjectNode(JsonNodeFactory.instance);
+
+ if (StringUtils.isNotBlank(edmType)) {
+ propertyNode.put(JSON_ODATAMETADATA_NAME, ODATA_METADATA_PREFIX + edmType);
+ }
+
+ JsonNode jsonNode = getProperty(srcNode, path);
+
+ if (jsonNode.isArray()) {
+ propertyNode.put("value", (ArrayNode) jsonNode);
+ } else if (jsonNode.isObject()) {
+ propertyNode.putAll((ObjectNode) jsonNode);
+ } else {
+ propertyNode.put("value", jsonNode.asText());
+ }
+
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ mapper.writeValue(bos, propertyNode);
+
+ final InputStream res = new ByteArrayInputStream(bos.toByteArray());
+ IOUtils.closeQuietly(bos);
+
+ return res;
+ }
+
+ private JsonNode getProperty(final JsonNode node, final List<String> path)
+ throws NotFoundException {
+
+ JsonNode propertyNode = node;
+ for (int i = 0; i < path.size(); i++) {
+ propertyNode = propertyNode.get(path.get(i));
+ if (propertyNode == null) {
+ throw new NotFoundException();
+ }
+ }
+
+ return propertyNode;
+ }
+
+ public InputStream addJsonInlinecount(
+ final InputStream src, final int count, final Accept accept)
+ throws Exception {
+ final ObjectMapper mapper = new ObjectMapper();
+ final JsonNode srcNode = mapper.readTree(src);
+
+ ((ObjectNode) srcNode).put(ODATA_COUNT_NAME, count);
+
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ mapper.writeValue(bos, srcNode);
+
+ final InputStream res = new ByteArrayInputStream(bos.toByteArray());
+ IOUtils.closeQuietly(bos);
+
+ return res;
+ }
+
+ public InputStream wrapJsonEntities(final InputStream entities) throws Exception {
+ final ObjectMapper mapper = new ObjectMapper();
+ final JsonNode node = mapper.readTree(entities);
+
+ final ObjectNode res;
+
+ final JsonNode value = node.get(JSON_VALUE_NAME);
+
+ if (value.isArray()) {
+ res = mapper.createObjectNode();
+ res.set("value", value);
+ final JsonNode next = node.get(JSON_NEXTLINK_NAME);
+ if (next != null) {
+ res.set(JSON_NEXTLINK_NAME, next);
+ }
+ } else {
+ res = (ObjectNode) value;
+ }
+
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ mapper.writeValue(bos, res);
+
+ final InputStream is = new ByteArrayInputStream(bos.toByteArray());
+ IOUtils.closeQuietly(bos);
+
+ return is;
+ }
+
+ @Override
+ public InputStream selectEntity(final InputStream src, final String[] propertyNames) throws Exception {
+ final ObjectMapper mapper = new ObjectMapper();
+ final ObjectNode srcNode = (ObjectNode) mapper.readTree(src);
+
+ final Set<String> retain = new HashSet<String>();
+ retain.add(JSON_ID_NAME);
+ retain.add(JSON_TYPE_NAME);
+ retain.add(JSON_EDITLINK_NAME);
+ retain.add(JSON_NEXTLINK_NAME);
+ retain.add(JSON_ODATAMETADATA_NAME);
+ retain.add(JSON_VALUE_NAME);
+
+ for (String name : propertyNames) {
+ retain.add(name);
+ retain.add(name + JSON_NAVIGATION_SUFFIX);
+ retain.add(name + JSON_MEDIA_SUFFIX);
+ retain.add(name + JSON_TYPE_SUFFIX);
+ }
+
+ srcNode.retain(retain);
+
+ return IOUtils.toInputStream(srcNode.toString());
+ }
+
+ @Override
+ public InputStream readEntities(
+ final List<String> links, final String linkName, final String next, final boolean forceFeed)
+ throws Exception {
+
+ if (links.isEmpty()) {
+ throw new NotFoundException();
+ }
+
+ final ObjectMapper mapper = new ObjectMapper();
+ final ObjectNode node = mapper.createObjectNode();
+
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+ if (forceFeed || links.size() > 1) {
+ bos.write("[".getBytes());
+ }
+
+ for (String link : links) {
+ try {
+ final Map.Entry<String, String> uri = Commons.parseEntityURI(link);
+ final Map.Entry<String, InputStream> entity =
+ readEntity(uri.getKey(), uri.getValue(), Accept.JSON_FULLMETA);
+
+ if (bos.size() > 1) {
+ bos.write(",".getBytes());
+ }
+
+ IOUtils.copy(entity.getValue(), bos);
+ } catch (Exception e) {
+ // log and ignore link
+ LOG.warn("Error parsing uri {}", link, e);
+ }
+ }
+
+ if (forceFeed || links.size() > 1) {
+ bos.write("]".getBytes());
+ }
+
+ node.set(JSON_VALUE_NAME, mapper.readTree(new ByteArrayInputStream(bos.toByteArray())));
+
+ if (StringUtils.isNotBlank(next)) {
+ node.set(JSON_NEXTLINK_NAME, new TextNode(next));
+ }
+
+ return IOUtils.toInputStream(node.toString());
+ }
+
+ @Override
+ protected InputStream replaceLink(
+ final InputStream toBeChanged, final String linkName, final InputStream replacement)
+ throws Exception {
+ final ObjectMapper mapper = new ObjectMapper();
+
+ final ObjectNode toBeChangedNode = (ObjectNode) mapper.readTree(toBeChanged);
+ final ObjectNode replacementNode = (ObjectNode) mapper.readTree(replacement);
+
+ if (toBeChangedNode.get(linkName + JSON_NAVIGATION_SUFFIX) == null) {
+ throw new NotFoundException();
+ }
+
+ toBeChangedNode.set(linkName, replacementNode.get(JSON_VALUE_NAME));
+
+ final JsonNode next = replacementNode.get(linkName + JSON_NEXTLINK_NAME);
+ if (next != null) {
+ toBeChangedNode.set(linkName + JSON_NEXTLINK_SUFFIX, next);
+ }
+
+ return IOUtils.toInputStream(toBeChangedNode.toString());
+ }
+
+ @Override
+ protected Map<String, InputStream> getChanges(final InputStream src) throws Exception {
+ final Map<String, InputStream> res = new HashMap<String, InputStream>();
+
+ final ObjectMapper mapper = new ObjectMapper();
+ final JsonNode srcObject = mapper.readTree(src);
+
+ final Iterator<Map.Entry<String, JsonNode>> fields = srcObject.fields();
+ while (fields.hasNext()) {
+ final Map.Entry<String, JsonNode> field = fields.next();
+ res.put(field.getKey(), IOUtils.toInputStream(field.getValue().toString()));
+ }
+
+ return res;
+ }
+
+ @Override
+ protected InputStream setChanges(
+ final InputStream toBeChanged, final Map<String, InputStream> properties) throws Exception {
+
+ final ObjectMapper mapper = new ObjectMapper();
+ final ObjectNode toBeChangedObject = (ObjectNode) mapper.readTree(toBeChanged);
+
+ for (Map.Entry<String, InputStream> property : properties.entrySet()) {
+ final JsonNode propertyNode = mapper.readTree(property.getValue());
+ toBeChangedObject.set(property.getKey(), propertyNode);
+ }
+
+ return IOUtils.toInputStream(toBeChangedObject.toString());
+ }
+
+ @Override
+ public Map.Entry<String, List<String>> extractLinkURIs(
+ final String entitySetName, final String entityId, final String linkName)
+ throws Exception {
+ final LinkInfo links = readLinks(entitySetName, entityId, linkName, Accept.JSON_FULLMETA);
+ return extractLinkURIs(links.getLinks());
+ }
+
+ @Override
+ public Map.Entry<String, List<String>> extractLinkURIs(final InputStream is)
+ throws Exception {
+ final ObjectMapper mapper = new ObjectMapper();
+ final ObjectNode srcNode = (ObjectNode) mapper.readTree(is);
+ IOUtils.closeQuietly(is);
+
+ final List<String> links = new ArrayList<String>();
+
+ JsonNode uris = srcNode.get("value");
+ if (uris == null) {
+ final JsonNode url = srcNode.get("url");
+ if (url != null) {
+ links.add(url.textValue());
+ }
+ } else {
+ final Iterator<JsonNode> iter = ((ArrayNode) uris).iterator();
+ while (iter.hasNext()) {
+ links.add(iter.next().get("url").textValue());
+ }
+ }
+
+ final JsonNode next = srcNode.get(JSON_NEXTLINK_NAME);
+
+ return new SimpleEntry<String, List<String>>(next == null ? null : next.asText(), links);
+ }
+
+ @Override
+ public InputStream addEditLink(
+ final InputStream content, final String title, final String href) throws Exception {
+ final ObjectMapper mapper = new ObjectMapper();
+ final ObjectNode srcNode = (ObjectNode) mapper.readTree(content);
+ IOUtils.closeQuietly(content);
+
+ srcNode.set(JSON_EDITLINK_NAME, new TextNode(href));
+ return IOUtils.toInputStream(srcNode.toString());
+ }
+
+ @Override
+ public InputStream replaceProperty(
+ final InputStream src, final InputStream replacement, final List<String> path, final boolean justValue)
+ throws Exception {
+ final ObjectMapper mapper = new ObjectMapper();
+ final ObjectNode srcNode = (ObjectNode) mapper.readTree(src);
+ IOUtils.closeQuietly(src);
+
+ final JsonNode replacementNode;
+ if (justValue) {
+ replacementNode = new TextNode(IOUtils.toString(replacement));
+ } else {
+ replacementNode = (ObjectNode) mapper.readTree(replacement);
+ }
+ IOUtils.closeQuietly(replacement);
+
+ JsonNode node = srcNode;
+ for (int i = 0; i < path.size() - 1; i++) {
+ node = node.get(path.get(i));
+ if (node == null) {
+ throw new NotFoundException();
+ }
+ }
+
+ ((ObjectNode) node).set(path.get(path.size() - 1), replacementNode);
+
+ return IOUtils.toInputStream(srcNode.toString());
+ }
+
+ @Override
+ public InputStream deleteProperty(final InputStream src, final List<String> path) throws Exception {
+ final ObjectMapper mapper = new ObjectMapper();
+ final ObjectNode srcNode = (ObjectNode) mapper.readTree(src);
+ IOUtils.closeQuietly(src);
+
+ JsonNode node = srcNode;
+ for (int i = 0; i < path.size() - 1; i++) {
+ node = node.get(path.get(i));
+ if (node == null) {
+ throw new NotFoundException();
+ }
+ }
+
+ ((ObjectNode) node).set(path.get(path.size() - 1), null);
+
+ return IOUtils.toInputStream(srcNode.toString());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/9aefb959/fit/src/main/java/org/apache/olingo/fit/utils/AbstractUtilities.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/utils/AbstractUtilities.java b/fit/src/main/java/org/apache/olingo/fit/utils/AbstractUtilities.java
index 74653a1..7b74b62 100644
--- a/fit/src/main/java/org/apache/olingo/fit/utils/AbstractUtilities.java
+++ b/fit/src/main/java/org/apache/olingo/fit/utils/AbstractUtilities.java
@@ -384,7 +384,7 @@ public abstract class AbstractUtilities {
}
if (accept != null) {
- builder.header("Content-Type", accept.toString());
+ builder.header("Content-Type", accept.toString(version));
} else {
builder.header("Content-Type", "*/*");
}
@@ -423,7 +423,6 @@ public abstract class AbstractUtilities {
public Response createFaultResponse(final String accept, final Exception e) {
LOG.debug("Create fault response about .... ", e);
- e.printStackTrace();
final Response.ResponseBuilder builder = Response.serverError();
if (version == ODataVersion.v3) {
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/9aefb959/fit/src/main/java/org/apache/olingo/fit/utils/AbstractXMLUtilities.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/utils/AbstractXMLUtilities.java b/fit/src/main/java/org/apache/olingo/fit/utils/AbstractXMLUtilities.java
new file mode 100644
index 0000000..d02e828
--- /dev/null
+++ b/fit/src/main/java/org/apache/olingo/fit/utils/AbstractXMLUtilities.java
@@ -0,0 +1,1302 @@
+/*
+ * 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.fit.utils;
+
+import static org.apache.olingo.fit.utils.Constants.*;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.StringWriter;
+import java.util.AbstractMap;
+import java.util.AbstractMap.SimpleEntry;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.ws.rs.NotFoundException;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLEventFactory;
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLEventWriter;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.Attribute;
+import javax.xml.stream.events.StartElement;
+import javax.xml.stream.events.XMLEvent;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.vfs2.FileObject;
+import org.apache.commons.vfs2.FileSystemException;
+
+public abstract class AbstractXMLUtilities extends AbstractUtilities {
+
+ protected static XMLInputFactory ifactory = null;
+
+ protected static XMLOutputFactory ofactory = null;
+
+ public AbstractXMLUtilities(final ODataVersion version) throws Exception {
+ super(version);
+ }
+
+ public abstract void retrieveLinkInfoFromMetadata() throws Exception;
+
+ @Override
+ protected Accept getDefaultFormat() {
+ return Accept.ATOM;
+ }
+
+ protected XMLEventReader getEventReader(final InputStream is) throws XMLStreamException {
+ if (ifactory == null) {
+ ifactory = XMLInputFactory.newInstance();
+ }
+ ifactory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, false);
+ return ifactory.createXMLEventReader(is);
+ }
+
+ protected static XMLEventWriter getEventWriter(final OutputStream os) throws XMLStreamException {
+ if (ofactory == null) {
+ ofactory = XMLOutputFactory.newInstance();
+ }
+
+ return ofactory.createXMLEventWriter(os);
+ }
+
+ private void writeEvent(final XMLEvent event, final XMLEventWriter writer) {
+ if (writer != null) {
+ try {
+ writer.add(event);
+ } catch (XMLStreamException e) {
+ LOG.error("Error writing event {}", event, e);
+ }
+ }
+ }
+
+ private void skipElement(
+ final StartElement start,
+ final XMLEventReader reader,
+ final XMLEventWriter writer,
+ final boolean excludeStart)
+ throws Exception {
+
+ if (!excludeStart) {
+ writeEvent(start, writer);
+ }
+
+ int depth = 1;
+ boolean found = false;
+
+ while (reader.hasNext() && !found) {
+ final XMLEvent event = reader.nextEvent();
+
+ writeEvent(event, writer);
+
+ if (event.getEventType() == XMLStreamConstants.START_ELEMENT) {
+ depth++;
+ } else if (event.getEventType() == XMLStreamConstants.END_ELEMENT) {
+ depth--;
+ found = depth == 0 && start.getName().equals(event.asEndElement().getName());
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc }
+ */
+ @Override
+ protected InputStream addLinks(
+ final String entitySetName, final String entitykey, final InputStream is, final Set<String> links)
+ throws Exception {
+
+ // -----------------------------------------
+ // 0. Build reader and writer
+ // -----------------------------------------
+ final XMLEventReader reader = getEventReader(is);
+ final XMLEventFactory eventFactory = XMLEventFactory.newInstance();
+
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ final XMLEventWriter writer = getEventWriter(bos);
+ // -----------------------------------------
+ final Map.Entry<Integer, XmlElement> entry =
+ extractElement(reader, writer, Collections.singletonList("entry"), 0, 1, 1);
+
+ writer.add(entry.getValue().getStart());
+
+ // add for links
+ for (String link : links) {
+ final Set<Attribute> attributes = new HashSet<Attribute>();
+ attributes.add(eventFactory.createAttribute(new QName("title"), link));
+ attributes.add(eventFactory.createAttribute(new QName("href"),
+ Commons.getLinksURI(version, entitySetName, entitykey, link)));
+ attributes.add(eventFactory.createAttribute(new QName("rel"), Constants.ATOM_LINK_REL + link));
+ attributes.add(eventFactory.createAttribute(new QName("type"),
+ Commons.linkInfo.get(version).isFeed(entitySetName, link) ? Constants.ATOM_LINK_FEED
+ : Constants.ATOM_LINK_ENTRY));
+
+ writer.add(eventFactory.createStartElement(new QName(LINK), attributes.iterator(), null));
+ writer.add(eventFactory.createEndElement(new QName(LINK), null));
+ }
+
+ writer.add(entry.getValue().getContentReader());
+ writer.add(entry.getValue().getEnd());
+ writer.add(reader);
+ IOUtils.closeQuietly(is);
+
+ writer.flush();
+ writer.close();
+ reader.close();
+
+ return new ByteArrayInputStream(bos.toByteArray());
+ }
+
+ /**
+ * {@inheritDoc }
+ */
+ @Override
+ protected Set<String> retrieveAllLinkNames(final InputStream is) throws Exception {
+ final Set<String> links = new HashSet<String>();
+
+ final XMLEventReader reader = getEventReader(is);
+
+ try {
+
+ int startDepth = 0;
+
+ while (true) {
+ final Map.Entry<Integer, XmlElement> linkInfo =
+ extractElement(reader, null, Collections.<String>singletonList(LINK), startDepth, 2, 2);
+
+ startDepth = linkInfo.getKey();
+
+ links.add(linkInfo.getValue().getStart().getAttributeByName(new QName("title")).getValue());
+ }
+ } catch (Exception ignore) {
+ // ignore
+ } finally {
+ reader.close();
+ IOUtils.closeQuietly(is);
+ }
+
+ return links;
+ }
+
+ /**
+ * {@inheritDoc }
+ */
+ @Override
+ protected NavigationLinks retrieveNavigationInfo(
+ final String entitySetName, final InputStream is)
+ throws Exception {
+
+ final NavigationLinks links = new NavigationLinks();
+
+ final XMLEventReader reader = getEventReader(is);
+
+ try {
+ final List<Map.Entry<String, String>> filter = new ArrayList<Map.Entry<String, String>>();
+ filter.add(new AbstractMap.SimpleEntry<String, String>("type", "application/atom+xml;type=entry"));
+ filter.add(new AbstractMap.SimpleEntry<String, String>("type", "application/atom+xml;type=feed"));
+
+ int startDepth = 0;
+
+ while (true) {
+ // a. search for link with type attribute equals to "application/atom+xml;type=entry/feed"
+ final Map.Entry<Integer, XmlElement> linkInfo = extractElement(
+ reader, null, Collections.<String>singletonList(LINK), filter, true, startDepth, 2, 2);
+ final XmlElement link = linkInfo.getValue();
+ startDepth = linkInfo.getKey();
+
+ final String title = link.getStart().getAttributeByName(new QName("title")).getValue();
+
+ final Attribute hrefAttr = link.getStart().getAttributeByName(new QName("href"));
+ final String href = hrefAttr == null ? null : hrefAttr.getValue();
+
+ try {
+ final XmlElement inlineElement =
+ extractElement(link.getContentReader(), null, Collections.<String>singletonList(INLINE), 0, -1, -1).
+ getValue();
+ final XMLEventReader inlineReader = inlineElement.getContentReader();
+
+ try {
+ while (true) {
+ final XmlElement entry =
+ extractElement(inlineReader, null, Collections.<String>singletonList("entry"), 0, -1, -1).
+ getValue();
+ links.addInlines(title, entry.toStream());
+ }
+ } catch (Exception e) {
+ // Reached the end of document
+ }
+
+ inlineReader.close();
+ } catch (Exception ignore) {
+ // inline element not found (inlines are not mondatory).
+ if (StringUtils.isNotBlank(href) && entityUriPattern.matcher(href).matches()) {
+ links.addLinks(title, href.substring(href.lastIndexOf('/') + 1));
+ }
+ }
+ }
+ } catch (Exception ignore) {
+ // ignore
+ } finally {
+ reader.close();
+ }
+
+ return links;
+ }
+
+ /**
+ * {@inheritDoc }
+ */
+ @Override
+ protected InputStream normalizeLinks(
+ final String entitySetName, final String entityKey, final InputStream is, final NavigationLinks links)
+ throws Exception {
+
+ // -----------------------------------------
+ // 0. Build reader and writer
+ // -----------------------------------------
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ IOUtils.copy(is, bos);
+ is.close();
+
+ final ByteArrayOutputStream tmpBos = new ByteArrayOutputStream();
+ final XMLEventWriter writer = getEventWriter(tmpBos);
+
+ final XMLEventReader reader = getEventReader(new ByteArrayInputStream(bos.toByteArray()));
+ // -----------------------------------------
+
+ // -----------------------------------------
+ // 1. Normalize links
+ // -----------------------------------------
+ final Set<String> added = new HashSet<String>();
+
+ try {
+ final List<Map.Entry<String, String>> filter = new ArrayList<Map.Entry<String, String>>();
+ filter.add(new AbstractMap.SimpleEntry<String, String>("type", "application/atom+xml;type=entry"));
+ filter.add(new AbstractMap.SimpleEntry<String, String>("type", "application/atom+xml;type=feed"));
+
+ Map.Entry<Integer, XmlElement> linkInfo = null;
+
+ while (true) {
+ // a. search for link with type attribute equals to "application/atom+xml;type=entry/feed"
+ linkInfo = extractElement(
+ reader, writer, Collections.<String>singletonList(LINK), filter, true,
+ linkInfo == null ? 0 : linkInfo.getKey(), 2, 2);
+ final XmlElement link = linkInfo.getValue();
+
+ final String title = link.getStart().getAttributeByName(new QName("title")).getValue();
+
+ if (!added.contains(title)) {
+ added.add(title);
+
+ final String normalizedLink = String.format(
+ "<link href=\"%s(%s)/%s\" rel=\"%s\" title=\"%s\" type=\"%s\"/>",
+ entitySetName,
+ entityKey,
+ title,
+ link.getStart().getAttributeByName(new QName("rel")).getValue(),
+ title,
+ link.getStart().getAttributeByName(new QName("type")).getValue());
+
+ addAtomElement(IOUtils.toInputStream(normalizedLink), writer);
+ }
+ }
+ } catch (Exception ignore) {
+ // ignore
+ } finally {
+ writer.close();
+ reader.close();
+ }
+ // -----------------------------------------
+
+ // -----------------------------------------
+ // 2. Add edit link if missing
+ // -----------------------------------------
+ final InputStream content = addEditLink(
+ new ByteArrayInputStream(tmpBos.toByteArray()),
+ entitySetName,
+ Constants.DEFAULT_SERVICE_URL + entitySetName + "(" + entityKey + ")");
+ // -----------------------------------------
+
+ // -----------------------------------------
+ // 3. Add content element if missing
+ // -----------------------------------------
+ return addAtomContent(
+ content,
+ entitySetName,
+ Constants.DEFAULT_SERVICE_URL + entitySetName + "(" + entityKey + ")");
+ // -----------------------------------------
+
+ }
+
+ public XmlElement getXmlElement(
+ final StartElement start,
+ final XMLEventReader reader)
+ throws Exception {
+
+ final XmlElement res = new XmlElement();
+ res.setStart(start);
+
+ StringWriter content = new StringWriter();
+
+ int depth = 1;
+
+ while (reader.hasNext() && depth > 0) {
+ final XMLEvent event = reader.nextEvent();
+
+ if (event.getEventType() == XMLStreamConstants.START_ELEMENT) {
+ depth++;
+ } else if (event.getEventType() == XMLStreamConstants.END_ELEMENT) {
+ depth--;
+ }
+
+ if (depth == 0) {
+ res.setEnd(event.asEndElement());
+ } else {
+ event.writeAsEncodedUnicode(content);
+ }
+ }
+
+ content.flush();
+ content.close();
+
+ res.setContent(new ByteArrayInputStream(content.toString().getBytes()));
+
+ return res;
+ }
+
+ private void addAtomElement(
+ final InputStream content,
+ final XMLEventWriter writer)
+ throws Exception {
+ final XMLEventReader reader = getEventReader(content);
+
+ final XMLEventFactory eventFactory = XMLEventFactory.newInstance();
+ XMLEvent newLine = eventFactory.createSpace("\n");
+
+ try {
+ writer.add(newLine);
+
+ while (reader.hasNext()) {
+ final XMLEvent event = reader.nextEvent();
+
+ if (event.getEventType() != XMLStreamConstants.START_DOCUMENT
+ && event.getEventType() != XMLStreamConstants.END_DOCUMENT
+ && event.getEventType() != XMLStreamConstants.COMMENT) {
+ writer.add(event);
+ }
+ }
+ writer.add(newLine);
+ } finally {
+ reader.close();
+ IOUtils.closeQuietly(content);
+ }
+ }
+
+ @Override
+ public InputStream addEditLink(
+ final InputStream content, final String title, final String href)
+ throws Exception {
+
+ final ByteArrayOutputStream copy = new ByteArrayOutputStream();
+ IOUtils.copy(content, copy);
+
+ IOUtils.closeQuietly(content);
+
+ XMLEventReader reader = getEventReader(new ByteArrayInputStream(copy.toByteArray()));
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ XMLEventWriter writer = getEventWriter(bos);
+
+ final String editLinkElement = String.format("<link rel=\"edit\" title=\"%s\" href=\"%s\" />", title, href);
+
+ try {
+ // check edit link existence
+ extractElement(reader, writer, Collections.<String>singletonList(LINK),
+ Collections.<Map.Entry<String, String>>singletonList(
+ new AbstractMap.SimpleEntry<String, String>("rel", "edit")), false, 0, -1, -1);
+
+ addAtomElement(IOUtils.toInputStream(editLinkElement), writer);
+ writer.add(reader);
+
+ } catch (Exception e) {
+ reader.close();
+ reader = getEventReader(new ByteArrayInputStream(copy.toByteArray()));
+
+ bos = new ByteArrayOutputStream();
+ writer = getEventWriter(bos);
+
+ final XmlElement entryElement =
+ extractElement(reader, writer, Collections.<String>singletonList("entry"), 0, 1, 1).getValue();
+
+ writer.add(entryElement.getStart());
+
+ addAtomElement(IOUtils.toInputStream(editLinkElement), writer);
+
+ writer.add(entryElement.getContentReader());
+ writer.add(entryElement.getEnd());
+
+ writer.add(reader);
+
+ writer.flush();
+ writer.close();
+ } finally {
+ reader.close();
+ }
+
+ return new ByteArrayInputStream(bos.toByteArray());
+ }
+
+ public InputStream addAtomContent(
+ final InputStream content, final String title, final String href)
+ throws Exception {
+
+ final ByteArrayOutputStream copy = new ByteArrayOutputStream();
+ IOUtils.copy(content, copy);
+
+ IOUtils.closeQuietly(content);
+
+ XMLEventReader reader = getEventReader(new ByteArrayInputStream(copy.toByteArray()));
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ XMLEventWriter writer = getEventWriter(bos);
+
+ try {
+ // check edit link existence
+ XmlElement contentElement =
+ extractElement(reader, writer, Collections.<String>singletonList("content"), 0, 2, 2).getValue();
+ writer.add(contentElement.getStart());
+ writer.add(contentElement.getContentReader());
+ writer.add(contentElement.getEnd());
+ writer.add(reader);
+ } catch (Exception e) {
+ reader.close();
+ reader = getEventReader(new ByteArrayInputStream(copy.toByteArray()));
+
+ bos = new ByteArrayOutputStream();
+ writer = getEventWriter(bos);
+
+ if (isMediaContent(title)) {
+ final XmlElement entryElement =
+ extractElement(reader, writer, Collections.<String>singletonList("entry"), 0, 1, 1).getValue();
+
+ writer.add(entryElement.getStart());
+ writer.add(entryElement.getContentReader());
+
+ addAtomElement(
+ IOUtils.toInputStream(String.format("<content type=\"*/*\" src=\"%s/$value\" />", href)),
+ writer);
+
+ writer.add(entryElement.getEnd());
+ } else {
+ try {
+ final XmlElement entryElement =
+ extractElement(reader, writer, Collections.<String>singletonList(PROPERTIES), 0, 2, 3).getValue();
+
+ addAtomElement(
+ IOUtils.toInputStream("<content type=\"application/xml\">"),
+ writer);
+
+ writer.add(entryElement.getStart());
+ writer.add(entryElement.getContentReader());
+ writer.add(entryElement.getEnd());
+
+ addAtomElement(
+ IOUtils.toInputStream("</content>"),
+ writer);
+ } catch (Exception nf) {
+ reader.close();
+ reader = getEventReader(new ByteArrayInputStream(copy.toByteArray()));
+
+ bos = new ByteArrayOutputStream();
+ writer = getEventWriter(bos);
+
+ final XmlElement entryElement =
+ extractElement(reader, writer, Collections.<String>singletonList("entry"), 0, 1, 1).getValue();
+ writer.add(entryElement.getStart());
+ writer.add(entryElement.getContentReader());
+
+ addAtomElement(
+ IOUtils.toInputStream("<content type=\"application/xml\"/>"),
+ writer);
+
+ writer.add(entryElement.getEnd());
+ }
+ }
+
+ writer.add(reader);
+
+ writer.flush();
+ writer.close();
+ } finally {
+ reader.close();
+ }
+
+ return new ByteArrayInputStream(bos.toByteArray());
+ }
+
+ public int countAllElements(final String entitySetName) throws Exception {
+ final String basePath = entitySetName + File.separatorChar;
+ int count = countFeedElements(fsManager.readFile(basePath + FEED, Accept.XML), "entry");
+
+ final String skipTokenDirPath = fsManager.getAbsolutePath(basePath + SKIP_TOKEN, null);
+
+
+ try {
+ final FileObject skipToken = fsManager.resolve(skipTokenDirPath);
+ final FileObject[] files = fsManager.findByExtension(skipToken, Accept.XML.getExtension().substring(1));
+
+ for (FileObject file : files) {
+ count += countFeedElements(fsManager.readFile(
+ basePath + SKIP_TOKEN + File.separatorChar + file.getName().getBaseName(), null), "entry");
+ }
+ } catch (FileSystemException fse) {
+ LOG.debug("Resource path '{}' not found", skipTokenDirPath);
+ }
+
+
+ return count;
+ }
+
+ private int countFeedElements(final InputStream is, final String elementName) throws XMLStreamException {
+ final XMLEventReader reader = getEventReader(is);
+
+ int count = 0;
+
+ while (reader.hasNext()) {
+ final XMLEvent event = reader.nextEvent();
+
+ if (event.getEventType() == XMLStreamConstants.START_ELEMENT
+ && elementName.equals(event.asStartElement().getName().getLocalPart())) {
+ count++;
+ }
+ }
+
+ reader.close();
+ return count;
+ }
+
+ public Map.Entry<Integer, XmlElement> extractElement(
+ final XMLEventReader reader, final XMLEventWriter writer, final List<String> path,
+ final int startPathPos, final int minPathPos, final int maxPathPos)
+ throws Exception {
+ return extractElement(reader, writer, path, null, false, startPathPos, minPathPos, maxPathPos);
+ }
+
+ public Map.Entry<Integer, XmlElement> extractElement(
+ final XMLEventReader reader, final XMLEventWriter writer, final List<String> path,
+ final Collection<Map.Entry<String, String>> filter,
+ final boolean filterInOr,
+ final int startPathPos, final int minPathPos, final int maxPathPos)
+ throws Exception {
+
+ StartElement start = null;
+ int searchFor = 0;
+ int depth = startPathPos;
+
+ // Current inspected element
+ String current = null;
+
+ // set defaults
+ final List<String> pathElementNames = path == null ? Collections.<String>emptyList() : path;
+ final Collection<Map.Entry<String, String>> filterAttrs =
+ filter == null ? Collections.<Map.Entry<String, String>>emptySet() : filter;
+
+ while (reader.hasNext() && start == null) {
+ final XMLEvent event = reader.nextEvent();
+
+ if (event.getEventType() == XMLStreamConstants.START_ELEMENT) {
+ depth++;
+
+ if (current != null || ((minPathPos < 0 || minPathPos <= depth) && (maxPathPos < 0 || depth <= maxPathPos))) {
+ if (pathElementNames.isEmpty()
+ || pathElementNames.get(searchFor).trim().equals(event.asStartElement().getName().getLocalPart())) {
+
+ if (searchFor < pathElementNames.size() - 1) {
+ // path exploring not completed
+ writeEvent(event, writer);
+ current = pathElementNames.get(searchFor).trim();
+ searchFor++;
+ } else {
+
+ // path exploring completed ... evaluate filter about path element name attribute
+ boolean match = filterAttrs.isEmpty() || !filterInOr;
+
+ for (Map.Entry<String, String> filterAttr : filterAttrs) {
+ final Attribute attr = event.asStartElement().getAttributeByName(new QName(filterAttr.getKey().trim()));
+
+ if (attr == null || !filterAttr.getValue().trim().equals(attr.getValue())) {
+ match = filterInOr ? match : false;
+ } else {
+ match = filterInOr ? true : match;
+ }
+ }
+
+ if (match) {
+ // found searched element
+ start = event.asStartElement();
+ } else {
+ skipElement(event.asStartElement(), reader, writer, false);
+ depth--;
+ }
+ }
+ } else if (current == null) {
+ writeEvent(event, writer);
+ } else {
+ // skip element
+ skipElement(event.asStartElement(), reader, writer, false);
+ depth--;
+ }
+ } else {
+ writeEvent(event, writer);
+ }
+
+ } else if (event.getEventType() == XMLStreamConstants.END_ELEMENT) {
+ depth--;
+
+ writeEvent(event, writer);
+
+ if (event.asEndElement().getName().getLocalPart().equals(current)) {
+ // back step ....
+ searchFor--;
+ current = searchFor > 0 ? pathElementNames.get(searchFor - 1).trim() : null;
+ }
+ } else {
+ writeEvent(event, writer);
+ }
+ }
+
+ if (start == null) {
+ throw new NotFoundException();
+ }
+
+ return new SimpleEntry<Integer, XmlElement>(Integer.valueOf(depth - 1), getXmlElement(start, reader));
+ }
+
+ public InputStream addAtomInlinecount(
+ final InputStream feed, final int count, final Accept accept)
+ throws Exception {
+ final XMLEventReader reader = getEventReader(feed);
+
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ final XMLEventWriter writer = getEventWriter(bos);
+
+ try {
+
+ final XmlElement feedElement =
+ extractElement(reader, writer, Collections.<String>singletonList("feed"), 0, 1, 1).getValue();
+
+ writer.add(feedElement.getStart());
+ addAtomElement(IOUtils.toInputStream(String.format("<m:count>%d</m:count>", count)), writer);
+ writer.add(feedElement.getContentReader());
+ writer.add(feedElement.getEnd());
+
+ while (reader.hasNext()) {
+ writer.add(reader.nextEvent());
+ }
+
+ } finally {
+ writer.flush();
+ writer.close();
+ reader.close();
+ IOUtils.closeQuietly(feed);
+ }
+
+ return new ByteArrayInputStream(bos.toByteArray());
+ }
+
+ @Override
+ public InputStream getPropertyValue(final InputStream is, final List<String> path)
+ throws Exception {
+
+ final List<String> pathElements = new ArrayList<String>();
+
+ for (String element : path) {
+ pathElements.add(ATOM_PROPERTY_PREFIX + element);
+ }
+
+ final XMLEventReader reader = getEventReader(is);
+ final Map.Entry<Integer, XmlElement> property = extractElement(reader, null, pathElements, 0, 3, 4);
+
+ reader.close();
+ IOUtils.closeQuietly(is);
+
+ return property.getValue().getContent();
+ }
+
+ @Override
+ public InputStream selectEntity(final InputStream entity, final String[] propertyNames) throws Exception {
+ final XMLEventReader reader = getEventReader(entity);
+
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ final XMLEventWriter writer = getEventWriter(bos);
+
+ final List<String> found = new ArrayList<String>(Arrays.asList(propertyNames));
+
+ boolean inProperties = false;
+ boolean writeCurrent = true;
+ Boolean writeNext = null;
+ String currentName = null;
+
+ final List<String> fieldToBeSaved = new ArrayList<String>(Arrays.asList(propertyNames));
+
+ while (reader.hasNext()) {
+ final XMLEvent event = reader.nextEvent();
+ if (event.getEventType() == XMLStreamConstants.START_ELEMENT
+ && LINK.equals(event.asStartElement().getName().getLocalPart())
+ && !fieldToBeSaved.contains(
+ event.asStartElement().getAttributeByName(new QName("title")).getValue())
+ && !"edit".equals(event.asStartElement().getAttributeByName(new QName("rel")).getValue())) {
+ writeCurrent = false;
+ } else if (event.getEventType() == XMLStreamConstants.END_ELEMENT
+ && LINK.equals(event.asEndElement().getName().getLocalPart())) {
+ writeNext = true;
+ } else if (event.getEventType() == XMLStreamConstants.START_ELEMENT
+ && (PROPERTIES).equals(event.asStartElement().getName().getLocalPart())) {
+ writeCurrent = true;
+ writeNext = false;
+ inProperties = true;
+ } else if (event.getEventType() == XMLStreamConstants.END_ELEMENT
+ && (PROPERTIES).equals(event.asEndElement().getName().getLocalPart())) {
+ writeCurrent = true;
+ } else if (inProperties) {
+ if (event.getEventType() == XMLStreamConstants.START_ELEMENT) {
+ final String elementName = event.asStartElement().getName().getLocalPart();
+
+ for (String propertyName : propertyNames) {
+ if ((ATOM_PROPERTY_PREFIX + propertyName.trim()).equals(elementName)) {
+ writeCurrent = true;
+ found.remove(propertyName);
+ currentName = propertyName;
+ }
+ }
+
+ } else if (event.getEventType() == XMLStreamConstants.END_ELEMENT
+ && StringUtils.isNotBlank(currentName)
+ && (ATOM_PROPERTY_PREFIX + currentName.trim()).equals(
+ event.asEndElement().getName().getLocalPart())) {
+ writeNext = false;
+ currentName = null;
+ }
+
+ }
+
+ if (writeCurrent) {
+ writer.add(event);
+ }
+
+ if (writeNext != null) {
+ writeCurrent = writeNext;
+ writeNext = null;
+ }
+ }
+
+ writer.flush();
+ writer.close();
+ reader.close();
+ IOUtils.closeQuietly(entity);
+
+ // Do not raise any exception in order to support FC properties as well
+ // if (!found.isEmpty()) {
+ // throw new Exception(String.format("Could not find a properties '%s'", found));
+ // }
+
+ return new ByteArrayInputStream(bos.toByteArray());
+ }
+
+ @Override
+ public InputStream readEntities(
+ final List<String> links, final String linkName, final String next, final boolean forceFeed)
+ throws Exception {
+
+ if (links.isEmpty()) {
+ throw new NotFoundException();
+ }
+
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+ if (forceFeed || links.size() > 1) {
+ // build a feed
+ bos.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>".getBytes());
+
+ bos.write(("<feed xml:base=\"" + DEFAULT_SERVICE_URL + "\" "
+ + "xmlns=\"http://www.w3.org/2005/Atom\" "
+ + "xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices\" "
+ + "xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\">")
+ .getBytes());
+
+ bos.write(("<id>" + DEFAULT_SERVICE_URL + "entityset(entityid)/" + linkName + "</id>").getBytes());
+
+ bos.write(("<title type=\"text\">" + linkName + "</title>").getBytes());
+ bos.write("<updated>2014-03-03T13:40:49Z</updated>".getBytes());
+ bos.write(("<link rel=\"self\" title=\"" + linkName + "\" href=\"" + linkName + "\" />").getBytes());
+ }
+
+ for (String link : links) {
+ try {
+ final Map.Entry<String, String> uri = Commons.parseEntityURI(link);
+
+ final XmlElement entry =
+ extractElement(
+ getEventReader(readEntity(uri.getKey(), uri.getValue(), Accept.ATOM).getValue()),
+ null,
+ Collections.<String>singletonList("entry"),
+ 0, 1, 1).getValue();
+
+ IOUtils.copy(entry.toStream(), bos);
+ } catch (Exception e) {
+ // log and ignore link
+ LOG.warn("Error parsing uri {}", link, e);
+ }
+ }
+
+ if (forceFeed || links.size() > 1) {
+
+ if (StringUtils.isNotBlank(next)) {
+ bos.write(String.format("<link rel=\"next\" href=\"%s\" />", next).getBytes());
+ }
+
+ bos.write("</feed>".getBytes());
+ }
+
+ return new ByteArrayInputStream(bos.toByteArray());
+ }
+
+ @Override
+ public Map<String, InputStream> getChanges(final InputStream src) throws Exception {
+ final Map<String, InputStream> res = new HashMap<String, InputStream>();
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ IOUtils.copy(src, bos);
+ IOUtils.closeQuietly(src);
+
+ // retrieve properties ...
+ XMLEventReader reader = getEventReader(new ByteArrayInputStream(bos.toByteArray()));
+
+ final Map.Entry<Integer, XmlElement> propertyElement =
+ extractElement(reader, null, Collections.<String>singletonList(PROPERTIES), 0, 2, 3);
+ reader.close();
+
+ reader = propertyElement.getValue().getContentReader();
+
+ try {
+ while (true) {
+ final XmlElement property = extractElement(reader, null, null, 0, -1, -1).getValue();
+ res.put(property.getStart().getName().getLocalPart(), property.toStream());
+ }
+ } catch (Exception ignore) {
+ // end
+ }
+
+ reader.close();
+
+ // retrieve links ...
+ reader = getEventReader(new ByteArrayInputStream(bos.toByteArray()));
+
+ try {
+ int pos = 0;
+ while (true) {
+ final Map.Entry<Integer, XmlElement> linkElement =
+ extractElement(reader, null, Collections.<String>singletonList(LINK), pos, 2, 2);
+
+ res.put("[LINK]" + linkElement.getValue().getStart().getAttributeByName(new QName("title")).getValue(),
+ linkElement.getValue().toStream());
+
+ pos = linkElement.getKey();
+ }
+ } catch (Exception ignore) {
+ // end
+ }
+
+ return res;
+ }
+
+ @Override
+ public InputStream setChanges(
+ final InputStream toBeChanged,
+ final Map<String, InputStream> properties)
+ throws Exception {
+ XMLEventReader reader = getEventReader(toBeChanged);
+
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ XMLEventWriter writer = getEventWriter(bos);
+
+ // ---------------------------------
+ // add property changes
+ // ---------------------------------
+ Map.Entry<Integer, XmlElement> propertyElement =
+ extractElement(reader, writer, Collections.<String>singletonList(PROPERTIES), 0, 2, 3);
+
+ writer.flush();
+
+ ByteArrayOutputStream pbos = new ByteArrayOutputStream();
+ OutputStreamWriter pwriter = new OutputStreamWriter(pbos);
+
+ final XMLEventReader propertyReader = propertyElement.getValue().getContentReader();
+
+ try {
+ while (true) {
+ final XmlElement property = extractElement(propertyReader, null, null, 0, -1, -1).getValue();
+ final String name = property.getStart().getName().getLocalPart();
+
+ if (properties.containsKey(name)) {
+ // replace
+ final InputStream replacement = properties.get(name);
+ properties.remove(property.getStart().getName().getLocalPart());
+ pwriter.append(IOUtils.toString(replacement));
+ IOUtils.closeQuietly(replacement);
+ } else {
+ pwriter.append(IOUtils.toString(property.toStream()));
+ }
+ }
+ } catch (Exception ignore) {
+ // end
+ }
+
+ for (Map.Entry<String, InputStream> remains : properties.entrySet()) {
+ if (!remains.getKey().startsWith("[LINK]")) {
+ pwriter.append(IOUtils.toString(remains.getValue()));
+ IOUtils.closeQuietly(remains.getValue());
+ }
+ }
+
+ pwriter.flush();
+ pwriter.close();
+
+ writer.add(propertyElement.getValue().getStart());
+ writer.add(new XMLEventReaderWrapper(new ByteArrayInputStream(pbos.toByteArray())));
+ writer.add(propertyElement.getValue().getEnd());
+
+ IOUtils.closeQuietly(pbos);
+
+ writer.add(reader);
+ reader.close();
+ writer.flush();
+ writer.close();
+ // ---------------------------------
+
+ // ---------------------------------
+ // add navigationm changes
+ // ---------------------------------
+
+ // remove existent links
+ for (Map.Entry<String, InputStream> remains : properties.entrySet()) {
+
+ if (remains.getKey().startsWith("[LINK]")) {
+ reader = getEventReader(new ByteArrayInputStream(bos.toByteArray()));
+
+ bos.reset();
+ writer = getEventWriter(bos);
+
+ try {
+ final String linkName = remains.getKey().substring(remains.getKey().indexOf("]") + 1);
+
+ extractElement(reader, writer, Collections.<String>singletonList(LINK),
+ Collections.<Map.Entry<String, String>>singleton(new SimpleEntry<String, String>("title", linkName)),
+ false, 0, 2, 2);
+
+ writer.add(reader);
+
+ } catch (Exception ignore) {
+ // ignore
+ }
+
+ writer.flush();
+ writer.close();
+ }
+ }
+
+ reader = getEventReader(new ByteArrayInputStream(bos.toByteArray()));
+
+ bos.reset();
+ writer = getEventWriter(bos);
+
+ propertyElement = extractElement(reader, writer, Collections.<String>singletonList(CONTENT), 0, 2, 2);
+ writer.flush();
+
+ pbos.reset();
+ pwriter = new OutputStreamWriter(pbos);
+
+ for (Map.Entry<String, InputStream> remains : properties.entrySet()) {
+ if (remains.getKey().startsWith("[LINK]")) {
+ pwriter.append(IOUtils.toString(remains.getValue()));
+ IOUtils.closeQuietly(remains.getValue());
+ }
+ }
+
+ pwriter.flush();
+ pwriter.close();
+
+ writer.add(new XMLEventReaderWrapper(new ByteArrayInputStream(pbos.toByteArray())));
+ IOUtils.closeQuietly(pbos);
+
+ writer.add(propertyElement.getValue().getStart());
+ writer.add(propertyElement.getValue().getContentReader());
+ writer.add(propertyElement.getValue().getEnd());
+
+ writer.add(reader);
+ reader.close();
+ writer.flush();
+ writer.close();
+ // ---------------------------------
+
+ return new ByteArrayInputStream(bos.toByteArray());
+ }
+
+ @Override
+ protected InputStream replaceLink(
+ final InputStream toBeChanged, final String linkName, final InputStream replacement)
+ throws Exception {
+ final XMLEventReader reader = getEventReader(toBeChanged);
+
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ final XMLEventWriter writer = getEventWriter(bos);
+
+ final XMLEventFactory eventFactory = XMLEventFactory.newInstance();
+ XMLEvent newLine = eventFactory.createSpace("\n");
+
+ try {
+ final XmlElement linkElement =
+ extractElement(reader, writer, Collections.<String>singletonList(LINK),
+ Collections.<Map.Entry<String, String>>singletonList(new SimpleEntry<String, String>("title", linkName)),
+ false, 0, -1, -1).getValue();
+ writer.add(linkElement.getStart());
+
+ // ------------------------------------------
+ // write inline ...
+ // ------------------------------------------
+ writer.add(newLine);
+ writer.add(eventFactory.createStartElement("m", null, "inline"));
+
+ addAtomElement(replacement, writer);
+
+ writer.add(eventFactory.createEndElement("m", null, "inline"));
+ writer.add(newLine);
+ // ------------------------------------------
+
+ writer.add(linkElement.getEnd());
+
+ writer.add(reader);
+ writer.flush();
+ writer.close();
+ } finally {
+ reader.close();
+ IOUtils.closeQuietly(toBeChanged);
+ }
+
+ return new ByteArrayInputStream(bos.toByteArray());
+ }
+
+ public String getEdmTypeFromAtom(final String entitySetName, final String entityId, final List<String> path)
+ throws Exception {
+ InputStream src = fsManager.readFile(Commons.getEntityBasePath(entitySetName, entityId) + ENTITY, Accept.XML);
+
+ final List<String> atomPathElements = new ArrayList<String>();
+
+ for (String element : path) {
+ atomPathElements.add(ATOM_PROPERTY_PREFIX + element);
+ }
+
+ final Map.Entry<Integer, XmlElement> prop = extractElement(getEventReader(src), null, atomPathElements, 0, 3, 4);
+ IOUtils.closeQuietly(src);
+
+ final Attribute type = prop.getValue().getStart().getAttributeByName(new QName(TYPE));
+
+ final String edmType;
+
+ if (type == null) {
+ edmType = Constants.ATOM_DEF_TYPE;
+ } else {
+ edmType = type.getValue();
+ }
+
+ return edmType;
+ }
+
+ @Override
+ public Map.Entry<String, List<String>> extractLinkURIs(
+ final String entitySetName, final String entityId, final String linkName)
+ throws Exception {
+ final LinkInfo links = readLinks(entitySetName, entityId, linkName, Accept.XML);
+ return extractLinkURIs(links.getLinks());
+ }
+
+ @Override
+ public Map.Entry<String, List<String>> extractLinkURIs(final InputStream is)
+ throws Exception {
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ IOUtils.copy(is, bos);
+ IOUtils.closeQuietly(is);
+
+ XMLEventReader reader = getEventReader(new ByteArrayInputStream(bos.toByteArray()));
+ final List<String> links = new ArrayList<String>();
+ try {
+ while (true) {
+ links.add(IOUtils.toString(extractElement(reader, null, Collections.<String>singletonList("uri"), 0, -1, -1).
+ getValue().getContent()));
+ }
+ } catch (Exception ignore) {
+ // End document reached ...
+ }
+ reader.close();
+
+ String next;
+
+ reader = getEventReader(new ByteArrayInputStream(bos.toByteArray()));
+ try {
+ next = IOUtils.toString(extractElement(reader, null, Collections.<String>singletonList("next"), 0, -1, -1).
+ getValue().getContent());
+ } catch (Exception ignore) {
+ // next link is not mandatory
+ next = null;
+ }
+ reader.close();
+
+ return new AbstractMap.SimpleEntry<String, List<String>>(next, links);
+ }
+
+ @Override
+ public InputStream getProperty(
+ final String entitySetName, final String entityId, final List<String> path, final String edmType)
+ throws Exception {
+ final List<String> pathElements = new ArrayList<String>();
+
+ for (String element : path) {
+ pathElements.add(ATOM_PROPERTY_PREFIX + element);
+ }
+
+ final InputStream src =
+ fsManager.readFile(Commons.getEntityBasePath(entitySetName, entityId) + ENTITY, Accept.XML);
+
+ final XMLEventReader reader = getEventReader(src);
+ final XmlElement property = extractElement(reader, null, pathElements, 0, 3, 4).getValue();
+
+ reader.close();
+ IOUtils.closeQuietly(src);
+
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ final XMLEventWriter writer = getEventWriter(bos);
+
+ final XMLEventFactory eventFactory = XMLEventFactory.newInstance();
+ writer.add(eventFactory.createStartDocument("UTF-8", "1.0"));
+ writer.add(property.getStart());
+
+ if (property.getStart().getAttributeByName(new QName(ATOM_DATASERVICE_NS)) == null) {
+ writer.add(eventFactory.createNamespace(ATOM_PROPERTY_PREFIX.substring(0, 1), DATASERVICES_NS));
+ }
+ if (property.getStart().getAttributeByName(new QName(ATOM_METADATA_NS)) == null) {
+ writer.add(eventFactory.createNamespace(ATOM_METADATA_PREFIX.substring(0, 1), METADATA_NS));
+ }
+
+ writer.add(property.getContentReader());
+ writer.add(property.getEnd());
+
+ writer.flush();
+ writer.close();
+
+ return new ByteArrayInputStream(bos.toByteArray());
+ }
+
+ @Override
+ public InputStream replaceProperty(
+ final InputStream src, final InputStream replacement, final List<String> path, final boolean justValue)
+ throws Exception {
+
+ final List<String> pathElements = new ArrayList<String>();
+
+ for (String element : path) {
+ pathElements.add(ATOM_PROPERTY_PREFIX + element);
+ }
+
+ final XMLEventReader reader = getEventReader(src);
+
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ final XMLEventWriter writer = getEventWriter(bos);
+
+ final Map.Entry<Integer, XmlElement> element = extractElement(reader, writer, pathElements, 0, 3, 4);
+
+ if (justValue) {
+ writer.add(element.getValue().getStart());
+ }
+
+ final XMLEventReader changesReader = new XMLEventReaderWrapper(replacement);
+
+ writer.add(changesReader);
+ changesReader.close();
+ IOUtils.closeQuietly(replacement);
+
+ if (justValue) {
+ writer.add(element.getValue().getEnd());
+ }
+
+ writer.add(reader);
+
+ reader.close();
+ IOUtils.closeQuietly(src);
+
+ writer.flush();
+ writer.close();
+
+ return new ByteArrayInputStream(bos.toByteArray());
+ }
+
+ @Override
+ public InputStream deleteProperty(final InputStream src, final List<String> path) throws Exception {
+
+ final List<String> pathElements = new ArrayList<String>();
+
+ for (String element : path) {
+ pathElements.add(ATOM_PROPERTY_PREFIX + element);
+ }
+
+ final XMLEventReader reader = getEventReader(src);
+
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ final XMLEventWriter writer = getEventWriter(bos);
+
+ final Map.Entry<Integer, XmlElement> element = extractElement(reader, writer, pathElements, 0, 3, 4);
+
+ final XMLEventReader changesReader = new XMLEventReaderWrapper(
+ IOUtils.toInputStream(String.format("<%s m:null=\"true\" />", path.get(path.size() - 1))));
+
+ writer.add(changesReader);
+ changesReader.close();
+
+ writer.add(reader);
+
+ reader.close();
+ IOUtils.closeQuietly(src);
+
+ writer.flush();
+ writer.close();
+
+ return new ByteArrayInputStream(bos.toByteArray());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/9aefb959/fit/src/main/java/org/apache/olingo/fit/utils/Accept.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/utils/Accept.java b/fit/src/main/java/org/apache/olingo/fit/utils/Accept.java
index 9fdf1da..2371843 100644
--- a/fit/src/main/java/org/apache/olingo/fit/utils/Accept.java
+++ b/fit/src/main/java/org/apache/olingo/fit/utils/Accept.java
@@ -28,24 +28,35 @@ public enum Accept {
TEXT(ContentType.TEXT_PLAIN.getMimeType(), ".txt"),
XML(ContentType.APPLICATION_XML.getMimeType(), ".xml"),
ATOM(ContentType.APPLICATION_ATOM_XML.getMimeType(), ".xml"),
- JSON(ContentType.APPLICATION_JSON.getMimeType() + ";odata=minimalmetadata", ".full.json"),
- JSON_NOMETA(ContentType.APPLICATION_JSON.getMimeType() + ";odata=nometadata", ".full.json"),
- JSON_FULLMETA(ContentType.APPLICATION_JSON.getMimeType() + ";odata=fullmetadata", ".full.json");
+ JSON(ContentType.APPLICATION_JSON.getMimeType() + ";odata=minimalmetadata",
+ ContentType.APPLICATION_JSON.getMimeType() + ";odata.metadata=minimal", ".full.json"),
+ JSON_NOMETA(ContentType.APPLICATION_JSON.getMimeType() + ";odata=nometadata",
+ ContentType.APPLICATION_JSON.getMimeType() + ";odata.metadata=none", ".full.json"),
+ JSON_FULLMETA(ContentType.APPLICATION_JSON.getMimeType() + ";odata=fullmetadata",
+ ContentType.APPLICATION_JSON.getMimeType() + ";odata.metadata=full", ".full.json");
- private final String contentType;
+ private final String contentTypeV3;
+
+ private final String contentTypeV4;
private final String fileExtension;
private static Pattern allTypesPattern = Pattern.compile("(.*,)?\\*/\\*([,;].*)?");
- Accept(final String contentType, final String fileExtension) {
- this.contentType = contentType;
+ Accept(final String contentTypeV3, final String fileExtension) {
+ this.contentTypeV3 = contentTypeV3;
+ this.contentTypeV4 = contentTypeV3;
+ this.fileExtension = fileExtension;
+ }
+
+ Accept(final String contentTypeV3, final String contentTypeV4, final String fileExtension) {
+ this.contentTypeV3 = contentTypeV3;
+ this.contentTypeV4 = contentTypeV4;
this.fileExtension = fileExtension;
}
- @Override
- public String toString() {
- return contentType;
+ public String toString(final ODataVersion version) {
+ return ODataVersion.v3 == version ? contentTypeV3 : contentTypeV4;
}
public String getExtension() {
@@ -53,23 +64,30 @@ public enum Accept {
}
public static Accept parse(final String contentType, final ODataVersion version) {
- return parse(contentType, version, ODataVersion.v3 == version ? ATOM : JSON_NOMETA);
+ final Accept def;
+ if (ODataVersion.v3 == version) {
+ def = ATOM;
+ } else {
+ def = JSON_NOMETA;
+ }
+
+ return parse(contentType, version, def);
}
public static Accept parse(final String contentType, final ODataVersion version, final Accept def) {
if (StringUtils.isBlank(contentType) || allTypesPattern.matcher(contentType).matches()) {
return def;
- } else if (JSON_NOMETA.toString().equals(contentType)) {
+ } else if (JSON_NOMETA.toString(version).equals(contentType)) {
return JSON_NOMETA;
- } else if (JSON.toString().equals(contentType) || "application/json".equals(contentType)) {
+ } else if (JSON.toString(version).equals(contentType) || "application/json".equals(contentType)) {
return JSON;
- } else if (JSON_FULLMETA.toString().equals(contentType)) {
+ } else if (JSON_FULLMETA.toString(version).equals(contentType)) {
return JSON_FULLMETA;
- } else if (XML.toString().equals(contentType)) {
+ } else if (XML.toString(version).equals(contentType)) {
return XML;
- } else if (ATOM.toString().equals(contentType)) {
+ } else if (ATOM.toString(version).equals(contentType)) {
return ATOM;
- } else if (TEXT.toString().equals(contentType)) {
+ } else if (TEXT.toString(version).equals(contentType)) {
return TEXT;
} else {
throw new UnsupportedMediaTypeException("Unsupported media type");
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/9aefb959/fit/src/main/java/org/apache/olingo/fit/utils/Commons.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/utils/Commons.java b/fit/src/main/java/org/apache/olingo/fit/utils/Commons.java
index 233e03d..dcc4807 100644
--- a/fit/src/main/java/org/apache/olingo/fit/utils/Commons.java
+++ b/fit/src/main/java/org/apache/olingo/fit/utils/Commons.java
@@ -74,6 +74,10 @@ public abstract class Commons {
mediaContent.put("Car/Photo", null);
}
+ public static Map<ODataVersion, MetadataLinkInfo> getLinkInfo() {
+ return linkInfo;
+ }
+
public static String getEntityURI(final String entitySetName, final String entityKey) {
return entitySetName + "(" + entityKey + ")";
}
@@ -230,7 +234,7 @@ public abstract class Commons {
break;
default:
- throw new UnsupportedOperationException(target.toString());
+ throw new UnsupportedOperationException(target.name());
}
for (String field : toBeRemoved) {