You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by fm...@apache.org on 2014/03/09 11:37:55 UTC
git commit: OLINGO-175 provided patch update and some refactorings
Repository: incubator-olingo-odata4
Updated Branches:
refs/heads/master 61b7b913a -> a9f74a87e
OLINGO-175 provided patch update and some refactorings
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/a9f74a87
Tree: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/tree/a9f74a87
Diff: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/diff/a9f74a87
Branch: refs/heads/master
Commit: a9f74a87e44c4a0a61ecae7e3a774a440359215d
Parents: 61b7b91
Author: fmartelli <fa...@gmail.com>
Authored: Sun Mar 9 11:37:41 2014 +0100
Committer: fmartelli <fa...@gmail.com>
Committed: Sun Mar 9 11:37:41 2014 +0100
----------------------------------------------------------------------
.../engine/it/EntityCreateTestITCase.java | 18 +-
.../engine/it/EntityUpdateTestITCase.java | 4 +-
.../testservice/AbstractServices.java | 116 ++++++++-----
.../odatajclient/testservice/methods/MERGE.java | 31 ++++
.../odatajclient/testservice/methods/PATCH.java | 32 ++++
.../testservice/utils/AbstractUtilities.java | 52 ++++--
.../odatajclient/testservice/utils/Commons.java | 8 +-
.../testservice/utils/Constants.java | 2 +
.../testservice/utils/JSONUtilities.java | 42 ++++-
.../testservice/utils/LinkInfo.java | 54 ++++++
.../testservice/utils/MetadataLinkInfo.java | 97 +++++++++++
.../utils/XMLEventReaderWrapper.java | 144 +++++++++++++++
.../testservice/utils/XMLUtilities.java | 174 ++++++++++++++++++-
.../testservice/utils/XmlElement.java | 110 +-----------
.../resources/v3/Product/-10/entity.full.json | 40 ++++-
.../main/resources/v3/Product/-10/entity.xml | 4 +-
.../src/main/resources/v3/Product/-10/etag.txt | 2 +-
17 files changed, 726 insertions(+), 204 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/a9f74a87/ODataJClient/engine/src/test/java/com/msopentech/odatajclient/engine/it/EntityCreateTestITCase.java
----------------------------------------------------------------------
diff --git a/ODataJClient/engine/src/test/java/com/msopentech/odatajclient/engine/it/EntityCreateTestITCase.java b/ODataJClient/engine/src/test/java/com/msopentech/odatajclient/engine/it/EntityCreateTestITCase.java
index d5edfcd..ce05ae1 100644
--- a/ODataJClient/engine/src/test/java/com/msopentech/odatajclient/engine/it/EntityCreateTestITCase.java
+++ b/ODataJClient/engine/src/test/java/com/msopentech/odatajclient/engine/it/EntityCreateTestITCase.java
@@ -204,7 +204,7 @@ public class EntityCreateTestITCase extends AbstractTestITCase {
public void createWithBackNavigationAsAtom() {
final ODataPubFormat format = ODataPubFormat.ATOM;
final ODataEntity actual = createWithBackNavigationLink(format, 9);
- cleanAfterCreate(format, actual, true, getOldServiceRoot());
+ cleanAfterCreate(format, actual, true, getServiceRoot());
}
@Test
@@ -212,7 +212,7 @@ public class EntityCreateTestITCase extends AbstractTestITCase {
// this needs to be full, otherwise there is no mean to recognize links
final ODataPubFormat format = ODataPubFormat.JSON_FULL_METADATA;
final ODataEntity actual = createWithBackNavigationLink(format, 10);
- cleanAfterCreate(format, actual, true, getOldServiceRoot());
+ cleanAfterCreate(format, actual, true, getServiceRoot());
}
@Test
@@ -379,7 +379,7 @@ public class EntityCreateTestITCase extends AbstractTestITCase {
final String sampleName = "Sample customer";
ODataEntity customer = getSampleCustomerProfile(id, sampleName, false);
- customer = createEntity(getOldServiceRoot(), format, customer, "Customer");
+ customer = createEntity(getServiceRoot(), format, customer, "Customer");
ODataEntity order = client.getObjectFactory().newEntity(
"Microsoft.Test.OData.Services.AstoriaDefaultService.Order");
@@ -389,19 +389,19 @@ public class EntityCreateTestITCase extends AbstractTestITCase {
client.getPrimitiveValueBuilder().setValue(id).setType(EdmSimpleType.Int32).build()));
order.addLink(client.getObjectFactory().newEntityNavigationLink(
- "Customer", URIUtils.getURI(getOldServiceRoot(), customer.getEditLink().toASCIIString())));
+ "Customer", URIUtils.getURI(getServiceRoot(), customer.getEditLink().toASCIIString())));
- order = createEntity(getOldServiceRoot(), format, order, "Order");
+ order = createEntity(getServiceRoot(), format, order, "Order");
ODataEntity changes = client.getObjectFactory().newEntity(
"Microsoft.Test.OData.Services.AstoriaDefaultService.Customer");
changes.setEditLink(customer.getEditLink());
changes.addLink(client.getObjectFactory().newFeedNavigationLink(
- "Orders", URIUtils.getURI(getOldServiceRoot(), order.getEditLink().toASCIIString())));
+ "Orders", URIUtils.getURI(getServiceRoot(), order.getEditLink().toASCIIString())));
update(UpdateType.PATCH, changes, format, null);
final ODataEntityRequest customerreq = client.getRetrieveRequestFactory().getEntityRequest(
- URIUtils.getURI(getOldServiceRoot(), order.getEditLink().toASCIIString() + "/Customer"));
+ URIUtils.getURI(getServiceRoot(), order.getEditLink().toASCIIString() + "/Customer"));
customerreq.setFormat(format);
customer = customerreq.execute().getBody();
@@ -410,7 +410,7 @@ public class EntityCreateTestITCase extends AbstractTestITCase {
Integer.valueOf(id), customer.getProperty("CustomerId").getPrimitiveValue().<Integer>toCastValue());
final ODataEntitySetRequest orderreq = client.getRetrieveRequestFactory().getEntitySetRequest(
- URIUtils.getURI(getOldServiceRoot(), customer.getEditLink().toASCIIString() + "/Orders"));
+ URIUtils.getURI(getServiceRoot(), customer.getEditLink().toASCIIString() + "/Orders"));
orderreq.setFormat(format);
final ODataRetrieveResponse<ODataEntitySet> orderres = orderreq.execute();
@@ -421,7 +421,7 @@ public class EntityCreateTestITCase extends AbstractTestITCase {
<Integer>toCastValue());
final ODataEntityRequest req = client.getRetrieveRequestFactory().getEntityRequest(
- URIUtils.getURI(getOldServiceRoot(), customer.getEditLink().toASCIIString() + "?$expand=Orders"));
+ URIUtils.getURI(getServiceRoot(), customer.getEditLink().toASCIIString() + "?$expand=Orders"));
req.setFormat(format);
customer = req.execute().getBody();
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/a9f74a87/ODataJClient/engine/src/test/java/com/msopentech/odatajclient/engine/it/EntityUpdateTestITCase.java
----------------------------------------------------------------------
diff --git a/ODataJClient/engine/src/test/java/com/msopentech/odatajclient/engine/it/EntityUpdateTestITCase.java b/ODataJClient/engine/src/test/java/com/msopentech/odatajclient/engine/it/EntityUpdateTestITCase.java
index 1bfd800..7984dd9 100644
--- a/ODataJClient/engine/src/test/java/com/msopentech/odatajclient/engine/it/EntityUpdateTestITCase.java
+++ b/ODataJClient/engine/src/test/java/com/msopentech/odatajclient/engine/it/EntityUpdateTestITCase.java
@@ -74,7 +74,7 @@ public class EntityUpdateTestITCase extends AbstractTestITCase {
@Test
public void patchAsAtom() {
final ODataPubFormat format = ODataPubFormat.ATOM;
- final URI uri = client.getURIBuilder(getServiceRoot()).
+ final URI uri = client.getURIBuilder(getStaticServiceRoot()).
appendEntityTypeSegment("Product").appendKeySegment(-10).build();
final String etag = getETag(uri);
final ODataEntity patch = client.getObjectFactory().newEntity(TEST_PRODUCT_TYPE);
@@ -85,7 +85,7 @@ public class EntityUpdateTestITCase extends AbstractTestITCase {
@Test
public void patchAsJSON() {
final ODataPubFormat format = ODataPubFormat.JSON_FULL_METADATA;
- final URI uri = client.getURIBuilder(getServiceRoot()).
+ final URI uri = client.getURIBuilder(getStaticServiceRoot()).
appendEntityTypeSegment("Product").appendKeySegment(-10).build();
final String etag = getETag(uri);
final ODataEntity patch = client.getObjectFactory().newEntity(TEST_PRODUCT_TYPE);
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/a9f74a87/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/AbstractServices.java
----------------------------------------------------------------------
diff --git a/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/AbstractServices.java b/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/AbstractServices.java
index 72140a9..726ccc8 100644
--- a/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/AbstractServices.java
+++ b/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/AbstractServices.java
@@ -19,7 +19,6 @@
package com.msopentech.odatajclient.testservice;
import com.msopentech.odatajclient.testservice.utils.Accept;
-import com.msopentech.odatajclient.testservice.utils.Commons;
import com.msopentech.odatajclient.testservice.utils.XMLUtilities;
import com.msopentech.odatajclient.testservice.utils.JSONUtilities;
import com.msopentech.odatajclient.testservice.utils.ODataVersion;
@@ -27,6 +26,10 @@ import com.msopentech.odatajclient.testservice.utils.FSManager;
import static com.msopentech.odatajclient.testservice.utils.Constants.*;
+import com.msopentech.odatajclient.testservice.methods.PATCH;
+import com.msopentech.odatajclient.testservice.utils.AbstractUtilities;
+import com.msopentech.odatajclient.testservice.utils.Commons;
+import com.msopentech.odatajclient.testservice.utils.LinkInfo;
import java.io.File;
import java.io.InputStream;
import java.util.Collections;
@@ -60,12 +63,12 @@ public abstract class AbstractServices {
protected abstract ODataVersion getVersion();
- protected final XMLUtilities atom;
+ protected final XMLUtilities xml;
protected final JSONUtilities json;
public AbstractServices() throws Exception {
- this.atom = new XMLUtilities(getVersion());
+ this.xml = new XMLUtilities(getVersion());
this.json = new JSONUtilities(getVersion());
}
@@ -84,10 +87,10 @@ public abstract class AbstractServices {
throw new UnsupportedMediaTypeException("Unsupported media type");
}
- return atom.createResponse(
+ return xml.createResponse(
FSManager.instance(getVersion()).readFile(SERVICES, acceptType), null, acceptType);
} catch (Exception e) {
- return atom.createFaultResponse(accept, e);
+ return xml.createFaultResponse(accept, e);
}
}
@@ -117,10 +120,36 @@ public abstract class AbstractServices {
private Response getMetadata(final String filename) {
try {
- return atom.
+ return xml.
createResponse(FSManager.instance(getVersion()).readFile(filename, Accept.XML), null, Accept.XML);
} catch (Exception e) {
- return atom.createFaultResponse(Accept.XML.toString(), e);
+ return xml.createFaultResponse(Accept.XML.toString(), e);
+ }
+ }
+
+ @PATCH
+ @Path("/{entitySetName}({entityId})")
+ @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON })
+ @Consumes({ MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON })
+ public Response patchEntity(
+ @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) String accept,
+ @HeaderParam("Prefer") @DefaultValue(StringUtils.EMPTY) String prefer,
+ @PathParam("entitySetName") String entitySetName,
+ @PathParam("entityId") String entityId,
+ final String changes) {
+
+ try {
+ final Accept acceptType = Accept.parse(accept, getVersion());
+
+ if (acceptType == Accept.XML || acceptType == Accept.TEXT) {
+ throw new UnsupportedMediaTypeException("Unsupported media type");
+ }
+
+ final AbstractUtilities util = acceptType == Accept.ATOM ? xml : json;
+ InputStream res = util.patchEntity(entitySetName, entityId, IOUtils.toInputStream(changes), acceptType);
+ return xml.createResponse(null, null, acceptType, Response.Status.NO_CONTENT);
+ } catch (Exception e) {
+ return xml.createFaultResponse(accept, e);
}
}
@@ -144,19 +173,18 @@ public abstract class AbstractServices {
final InputStream res;
if (acceptType == Accept.ATOM) {
- res = atom.saveSingleEntity(entityId, entitySetName, IOUtils.toInputStream(entity));
+ res = xml.saveSingleEntity(entityId, entitySetName, IOUtils.toInputStream(entity));
} else {
res = json.saveSingleEntity(entityId, entitySetName, IOUtils.toInputStream(entity));
}
res.close();
- final Response response = atom.createResponse(null, null, acceptType, Response.Status.NO_CONTENT);
+ final Response response = xml.createResponse(null, null, acceptType, Response.Status.NO_CONTENT);
response.getHeaders().put("Preference-Applied", Collections.<Object>singletonList(prefer));
return response;
} catch (Exception e) {
- e.printStackTrace();
- return atom.createFaultResponse(accept, e);
+ return xml.createFaultResponse(accept, e);
}
}
@@ -180,21 +208,21 @@ public abstract class AbstractServices {
final InputStream res;
if (acceptType == Accept.ATOM) {
- res = atom.createEntity(entitySetName, IOUtils.toInputStream(entity));
+ res = xml.createEntity(entitySetName, IOUtils.toInputStream(entity));
} else {
res = json.createEntity(entitySetName, IOUtils.toInputStream(entity));
}
if (prefer.equalsIgnoreCase("return-no-content")) {
res.close();
- Response response = atom.createResponse(null, null, acceptType, Response.Status.NO_CONTENT);
+ Response response = xml.createResponse(null, null, acceptType, Response.Status.NO_CONTENT);
response.getHeaders().put("Preference-Applied", Collections.<Object>singletonList(prefer));
return response;
} else {
- return atom.createResponse(res, null, acceptType, Response.Status.CREATED);
+ return xml.createResponse(res, null, acceptType, Response.Status.CREATED);
}
} catch (Exception e) {
- return atom.createFaultResponse(accept, e);
+ return xml.createFaultResponse(accept, e);
}
}
@@ -236,7 +264,7 @@ public abstract class AbstractServices {
try {
// search for function ...
final InputStream func = FSManager.instance(getVersion()).readFile(name, acceptType);
- return atom.createResponse(func, null, acceptType);
+ return xml.createResponse(func, null, acceptType);
} catch (NotFoundException e) {
// search for entitySet ...
final String basePath = name + File.separatorChar;
@@ -258,10 +286,10 @@ public abstract class AbstractServices {
InputStream feed = FSManager.instance(getVersion()).readFile(builder.toString(), acceptType);
if ("allpages".equals(inlinecount)) {
- int count = atom.countAllElements(name);
+ int count = xml.countAllElements(name);
feed.close();
if (acceptType == Accept.ATOM) {
- feed = atom.addAtomInlinecount(
+ feed = xml.addAtomInlinecount(
FSManager.instance(getVersion()).readFile(builder.toString(), acceptType),
count,
acceptType);
@@ -273,10 +301,10 @@ public abstract class AbstractServices {
}
}
- return atom.createResponse(feed, Commons.getETag(basePath, getVersion()), acceptType);
+ return xml.createResponse(feed, Commons.getETag(basePath, getVersion()), acceptType);
}
} catch (Exception e) {
- return atom.createFaultResponse(accept, e);
+ return xml.createFaultResponse(accept, e);
}
}
@@ -309,13 +337,13 @@ public abstract class AbstractServices {
acceptType = Accept.parse(accept, getVersion());
}
- final Map.Entry<String, InputStream> entityInfo = atom.readEntity(entitySetName, entityId, acceptType);
+ final Map.Entry<String, InputStream> entityInfo = xml.readEntity(entitySetName, entityId, acceptType);
InputStream entity = entityInfo.getValue();
if (StringUtils.isNotBlank(select)) {
if (acceptType == Accept.ATOM) {
- entity = atom.selectEntity(entity, select.split(","));
+ entity = xml.selectEntity(entity, select.split(","));
} else {
entity = json.selectEntity(entity, select.split(","));
}
@@ -326,7 +354,7 @@ public abstract class AbstractServices {
throw new UnsupportedMediaTypeException("Unsupported media type");
} else if (acceptType == Accept.ATOM) {
for (String exp : expand.split(",")) {
- entity = atom.expandEntity(
+ entity = xml.expandEntity(
entitySetName,
entityId,
entity,
@@ -343,10 +371,10 @@ public abstract class AbstractServices {
}
}
- return atom.createResponse(entity, Commons.getETag(entityInfo.getKey(), getVersion()), acceptType);
+ return xml.createResponse(entity, Commons.getETag(entityInfo.getKey(), getVersion()), acceptType);
} catch (Exception e) {
LOG.error("Error retrieving entity", e);
- return atom.createFaultResponse(accept, e);
+ return xml.createFaultResponse(accept, e);
}
}
@@ -362,9 +390,9 @@ public abstract class AbstractServices {
FSManager.instance(getVersion()).deleteFile(basePath + ENTITY);
- return atom.createResponse(null, null, null, Response.Status.NO_CONTENT);
+ return xml.createResponse(null, null, null, Response.Status.NO_CONTENT);
} catch (Exception e) {
- return atom.createFaultResponse(Accept.XML.toString(), e);
+ return xml.createFaultResponse(Accept.XML.toString(), e);
}
}
@@ -402,36 +430,36 @@ public abstract class AbstractServices {
InputStream stream;
try {
- final Map.Entry<String, List<String>> linkInfo = XMLUtilities.extractLinkURIs(
- atom.readLinks(entitySetName, entityId, path, Accept.XML).getValue());
+ final LinkInfo linkInfo = xml.readLinks(entitySetName, entityId, path, Accept.XML);
+ final Map.Entry<String, List<String>> links = XMLUtilities.extractLinkURIs(linkInfo.getLinks());
switch (acceptType) {
case JSON:
case JSON_FULLMETA:
case JSON_NOMETA:
- stream = json.readEntities(linkInfo.getValue(), path, linkInfo.getKey());
+ stream = json.readEntities(links.getValue(), path, links.getKey(), linkInfo.isFeed());
stream = json.wrapJsonEntities(stream);
break;
default:
- stream = atom.readEntities(linkInfo.getValue(), path, linkInfo.getKey());
+ stream = xml.readEntities(links.getValue(), path, links.getKey(), linkInfo.isFeed());
}
} catch (NotFoundException e) {
// if the given path is not about any link then search for property
LOG.info("Retrieve property {}", path);
stream = FSManager.instance(getVersion()).readFile(
- basePath + ENTITY, acceptType == null || acceptType == Accept.ATOM.TEXT
+ basePath + ENTITY, acceptType == null || acceptType == Accept.TEXT
? Accept.XML : acceptType);
if (searchForValue) {
- stream = atom.getAtomPropertyValue(stream, path.split("/"));
+ stream = xml.getAtomPropertyValue(stream, path.split("/"));
} else {
if (acceptType == null || acceptType == Accept.XML || acceptType == Accept.ATOM) {
// retrieve xml
- stream = atom.getAtomProperty(stream, path.split("/"));
+ stream = xml.getAtomProperty(stream, path.split("/"));
} else {
// retrieve Edm type from xml
- final String edmType = atom.getEdmTypeFromXML(
+ final String edmType = xml.getEdmTypeFromXML(
FSManager.instance(getVersion()).readFile(basePath + ENTITY, Accept.XML),
path.split("/"));
// retrieve json property
@@ -444,9 +472,9 @@ public abstract class AbstractServices {
}
}
- return atom.createResponse(stream, Commons.getETag(basePath, getVersion()), acceptType);
+ return xml.createResponse(stream, Commons.getETag(basePath, getVersion()), acceptType);
} catch (Exception e) {
- return atom.createFaultResponse(accept, e);
+ return xml.createFaultResponse(accept, e);
}
}
@@ -480,14 +508,14 @@ public abstract class AbstractServices {
throw new UnsupportedMediaTypeException("Unsupported media type");
}
- final Map.Entry<String, InputStream> links = atom.readLinks(entitySetName, entityId, linkName, acceptType);
+ final LinkInfo links = xml.readLinks(entitySetName, entityId, linkName, acceptType);
- return atom.createResponse(
- links.getValue(),
- links.getKey(),
+ return xml.createResponse(
+ links.getLinks(),
+ links.getEtag(),
acceptType);
} catch (Exception e) {
- return atom.createFaultResponse(accept, e);
+ return xml.createFaultResponse(accept, e);
}
}
@@ -510,14 +538,14 @@ public abstract class AbstractServices {
throw new UnsupportedMediaTypeException("Unsupported type " + accept);
}
- int count = atom.countAllElements(entitySetName);
+ int count = xml.countAllElements(entitySetName);
final Response.ResponseBuilder builder = Response.ok();
builder.entity(count);
return builder.build();
} catch (Exception e) {
- return atom.createFaultResponse(accept, e);
+ return xml.createFaultResponse(accept, e);
}
}
}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/a9f74a87/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/methods/MERGE.java
----------------------------------------------------------------------
diff --git a/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/methods/MERGE.java b/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/methods/MERGE.java
new file mode 100644
index 0000000..bdcd217
--- /dev/null
+++ b/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/methods/MERGE.java
@@ -0,0 +1,31 @@
+/**
+ * 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 com.msopentech.odatajclient.testservice.methods;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import javax.ws.rs.HttpMethod;
+
+@Target({ ElementType.METHOD })
+@Retention(RetentionPolicy.RUNTIME)
+@HttpMethod("MERGE")
+public @interface MERGE {
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/a9f74a87/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/methods/PATCH.java
----------------------------------------------------------------------
diff --git a/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/methods/PATCH.java b/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/methods/PATCH.java
new file mode 100644
index 0000000..6ebd38f
--- /dev/null
+++ b/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/methods/PATCH.java
@@ -0,0 +1,32 @@
+/**
+ * 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 com.msopentech.odatajclient.testservice.methods;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import javax.ws.rs.HttpMethod;
+
+@Target({ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@HttpMethod("PATCH")
+public @interface PATCH {
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/a9f74a87/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/AbstractUtilities.java
----------------------------------------------------------------------
diff --git a/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/AbstractUtilities.java b/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/AbstractUtilities.java
index 1fb30a8..3be3f02 100644
--- a/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/AbstractUtilities.java
+++ b/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/AbstractUtilities.java
@@ -34,7 +34,6 @@ import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
-import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -69,21 +68,20 @@ public abstract class AbstractUtilities {
}
private void initialize() throws Exception {
+
if (!initialized.contains(version)) {
+ final MetadataLinkInfo metadataLinkInfo = new MetadataLinkInfo();
+ Commons.linkInfo.put(version, metadataLinkInfo);
+
final InputStream metadata = fsManager.readFile(Constants.METADATA, Accept.XML);
final XMLEventReader reader = XMLUtilities.getEventReader(metadata);
- final Map<String, List<String>> entityLinksPerVersion = new HashMap<String, List<String>>();
- Commons.entityLinks.put(version, entityLinksPerVersion);
-
int initialDepth = 0;
try {
while (true) {
Map.Entry<Integer, XmlElement> entityType =
XMLUtilities.getAtomElement(reader, null, "EntityType", null, initialDepth, 4, 4, false);
initialDepth = entityType.getKey();
- entityLinksPerVersion.put(entityType.getValue().getStart().
- getAttributeByName(new QName("Name")).getValue(), new ArrayList<String>());
final XMLEventReader entityReader = XMLUtilities.getEventReader(entityType.getValue().toStream());
try {
@@ -93,9 +91,10 @@ public abstract class AbstractUtilities {
entityReader, null, "NavigationProperty", null, pos, 2, 2, false);
pos = navProperty.getKey();
- final List<String> links = entityLinksPerVersion.get(entityType.getValue().getStart().
- getAttributeByName(new QName("Name")).getValue());
- links.add(navProperty.getValue().
+ metadataLinkInfo.addLinkName(
+ entityType.getValue().getStart().
+ getAttributeByName(new QName("Name")).getValue(),
+ navProperty.getValue().
getStart().getAttributeByName(new QName("Name")).getValue());
}
} catch (Exception e) {
@@ -470,7 +469,7 @@ public abstract class AbstractUtilities {
* @param accept accept header.
* @return a pair of ETag/links stream
*/
- public Map.Entry<String, InputStream> readLinks(
+ public LinkInfo readLinks(
final String entitySetName, final String entityId, final String linkName, final Accept accept)
throws Exception {
@@ -478,8 +477,11 @@ public abstract class AbstractUtilities {
entitySetName + File.separatorChar + Commons.getEntityKey(entityId) + File.separatorChar
+ LINKS_FILE_PATH + File.separatorChar;
- return new SimpleEntry<String, InputStream>(
- Commons.getETag(basePath, version), fsManager.readFile(basePath + linkName, accept));
+ final LinkInfo linkInfo = new LinkInfo(fsManager.readFile(basePath + linkName, accept));
+ linkInfo.setEtag(Commons.getETag(basePath, version));
+ linkInfo.setFeed(Commons.feed.contains(entitySetName + "." + linkName));
+
+ return linkInfo;
}
public Map.Entry<String, InputStream> readEntity(
@@ -503,14 +505,18 @@ public abstract class AbstractUtilities {
// --------------------------------
// 0. Retrieve all 'linkName' navigation link uris (NotFoundException if missing)
// --------------------------------
- final Map.Entry<String, List<String>> linkInfo =
- XMLUtilities.extractLinkURIs(readLinks(entitySetName, entityId, linkName, Accept.XML).getValue());
+ final LinkInfo linkInfo = readLinks(entitySetName, entityId, linkName, Accept.XML);
+ final Map.Entry<String, List<String>> links = XMLUtilities.extractLinkURIs(linkInfo.getLinks());
// --------------------------------
// --------------------------------
// 1. Retrieve expanded object (entry or feed)
// --------------------------------
- final InputStream expanded = readEntities(linkInfo.getValue(), linkName, linkInfo.getKey());
+ final InputStream expanded = readEntities(
+ links.getValue(),
+ linkName,
+ links.getKey(),
+ linkInfo.isFeed());
// --------------------------------
// --------------------------------
@@ -520,8 +526,17 @@ public abstract class AbstractUtilities {
// --------------------------------
}
+ public InputStream patchEntity(
+ final String entitySetName, final String entityId, final InputStream changes, final Accept accept)
+ throws Exception {
+ final Map.Entry<String, InputStream> entityInfo = readEntity(entitySetName, entityId, accept);
+ final Map<String, InputStream> replacement = getChanges(changes);
+ return createEntity(entityId, entitySetName, setChanges(entityInfo.getValue(), replacement));
+ }
+
public abstract InputStream readEntities(
- final List<String> links, final String linkName, final String next) throws Exception;
+ final List<String> links, final String linkName, final String next, final boolean forceFeed)
+ throws Exception;
protected abstract InputStream replaceLink(
final InputStream toBeChanged, final String linkName, final InputStream replacement) throws Exception;
@@ -529,4 +544,9 @@ public abstract class AbstractUtilities {
public abstract InputStream selectEntity(final InputStream entity, final String[] propertyNames) throws Exception;
protected abstract Accept getDefaultFormat();
+
+ protected abstract Map<String, InputStream> getChanges(final InputStream src) throws Exception;
+
+ protected abstract InputStream setChanges(
+ final InputStream toBeChanged, final Map<String, InputStream> properties) throws Exception;
}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/a9f74a87/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/Commons.java
----------------------------------------------------------------------
diff --git a/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/Commons.java b/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/Commons.java
index 450fdb9..d3badbc 100644
--- a/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/Commons.java
+++ b/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/Commons.java
@@ -56,10 +56,12 @@ public abstract class Commons {
protected final static Set<String> mediaContent = new HashSet<String>();
+ protected final static Set<String> feed = new HashSet<String>();
+
protected final static Map<String, String> entitySetAlias = new HashMap<String, String>();
- protected final static Map<ODataVersion, Map<String, List<String>>> entityLinks =
- new EnumMap<ODataVersion, Map<String, List<String>>>(ODataVersion.class);
+ protected final static Map<ODataVersion, MetadataLinkInfo> linkInfo =
+ new EnumMap<ODataVersion, MetadataLinkInfo>(ODataVersion.class);
static {
sequence.put("Customer", 1000);
@@ -71,6 +73,8 @@ public abstract class Commons {
entitySetAlias.put("Customer.Info", "CustomerInfo");
entitySetAlias.put("Customer.Orders", "Order");
+ feed.add("Customer.Orders");
+ feed.add("Customer.Logins");
}
public static String getEntityKey(final String entityId) {
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/a9f74a87/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/Constants.java
----------------------------------------------------------------------
diff --git a/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/Constants.java b/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/Constants.java
index b523282..893158f 100644
--- a/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/Constants.java
+++ b/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/Constants.java
@@ -40,6 +40,8 @@ public class Constants {
public final static String INLINE = ATOM_METADATA_PREFIX + INLINE_LOCAL;
+ public final static String CONTENT = "content";
+
public final static String PROPERTIES = ATOM_METADATA_PREFIX + "properties";
public final static String LINK = "link";
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/a9f74a87/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/JSONUtilities.java
----------------------------------------------------------------------
diff --git a/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/JSONUtilities.java b/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/JSONUtilities.java
index e445ef4..9162067 100644
--- a/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/JSONUtilities.java
+++ b/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/JSONUtilities.java
@@ -30,6 +30,7 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -63,7 +64,6 @@ public class JSONUtilities extends AbstractUtilities {
final NavigationLinks links = new NavigationLinks();
final Iterator<Map.Entry<String, JsonNode>> fieldIter = srcNode.fields();
- final List<String> linksFromMeta = Commons.entityLinks.get(version).get(entitySetName);
while (fieldIter.hasNext()) {
final Map.Entry<String, JsonNode> field = fieldIter.next();
@@ -81,7 +81,7 @@ public class JSONUtilities extends AbstractUtilities {
}
links.addLinks(title, hrefs);
- } else if (linksFromMeta.contains(field.getKey())) {
+ } else if (Commons.linkInfo.get(version).exists(entitySetName, field.getKey())) {
links.addInlines(field.getKey(), IOUtils.toInputStream(field.getValue().toString()));
}
}
@@ -252,7 +252,8 @@ public class JSONUtilities extends AbstractUtilities {
}
@Override
- public InputStream readEntities(final List<String> links, final String linkName, final String next)
+ public InputStream readEntities(
+ final List<String> links, final String linkName, final String next, final boolean forceFeed)
throws Exception {
if (links.isEmpty()) {
@@ -264,7 +265,7 @@ public class JSONUtilities extends AbstractUtilities {
final ByteArrayOutputStream bos = new ByteArrayOutputStream();
- if (links.size() > 1) {
+ if (forceFeed || links.size() > 1) {
bos.write("[".getBytes());
}
@@ -280,7 +281,7 @@ public class JSONUtilities extends AbstractUtilities {
IOUtils.copy(entity.getValue(), bos);
}
- if (links.size() > 1) {
+ if (forceFeed || links.size() > 1) {
bos.write("]".getBytes());
}
@@ -311,4 +312,35 @@ public class JSONUtilities extends AbstractUtilities {
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());
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/a9f74a87/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/LinkInfo.java
----------------------------------------------------------------------
diff --git a/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/LinkInfo.java b/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/LinkInfo.java
new file mode 100644
index 0000000..39ea066
--- /dev/null
+++ b/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/LinkInfo.java
@@ -0,0 +1,54 @@
+/**
+ * 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 com.msopentech.odatajclient.testservice.utils;
+
+import java.io.InputStream;
+
+public class LinkInfo {
+
+ private final InputStream links;
+
+ private boolean feed = false;
+
+ private String etag;
+
+ public LinkInfo(final InputStream links) {
+ this.links = links;
+ }
+
+ public boolean isFeed() {
+ return feed;
+ }
+
+ public void setFeed(boolean feed) {
+ this.feed = feed;
+ }
+
+ public String getEtag() {
+ return etag;
+ }
+
+ public void setEtag(final String etag) {
+ this.etag = etag;
+ }
+
+ public InputStream getLinks() {
+ return links;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/a9f74a87/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/MetadataLinkInfo.java
----------------------------------------------------------------------
diff --git a/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/MetadataLinkInfo.java b/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/MetadataLinkInfo.java
new file mode 100644
index 0000000..794d480
--- /dev/null
+++ b/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/MetadataLinkInfo.java
@@ -0,0 +1,97 @@
+/**
+ * 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 com.msopentech.odatajclient.testservice.utils;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+public class MetadataLinkInfo {
+
+ protected final static Set<String> feed = new HashSet<String>();
+
+ protected final static Map<String, String> entitySetAlias = new HashMap<String, String>();
+
+ private Map<String, EntitySet> entitySets = new HashMap<String, EntitySet>();
+
+ public void addLinkName(final String entitySetName, final String linkName) {
+ final EntitySet entitySet;
+ if (entitySets.containsKey(entitySetName)) {
+ entitySet = entitySets.get(entitySetName);
+ } else {
+ entitySet = new EntitySet(entitySetName);
+ entitySets.put(entitySetName, entitySet);
+ }
+
+ entitySet.add(linkName);
+ }
+
+ public Collection<EntitySet> getEntitySets() {
+ return entitySets.values();
+ }
+
+ public Set<String> getNavigationLinkNames(final String entitySetName) {
+ return entitySets.containsKey(entitySetName)
+ ? entitySets.get(entitySetName).getLinks() : Collections.<String>emptySet();
+ }
+
+ public boolean exists(final String entitySetName, final String linkName) {
+ return getNavigationLinkNames(entitySetName).contains(linkName);
+ }
+
+ private static class EntitySet {
+
+ private String name;
+
+ private Set<String> links;
+
+ public EntitySet(final String name) {
+ this.name = name;
+ links = new HashSet<String>();
+ }
+
+ public void add(final String linkName) {
+ links.add(linkName);
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public Set<String> getLinks() {
+ return links;
+ }
+
+ public void setLinks(final Set<String> links) {
+ this.links = links;
+ }
+
+ @Override
+ public String toString() {
+ return name + ": " + links;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/a9f74a87/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/XMLEventReaderWrapper.java
----------------------------------------------------------------------
diff --git a/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/XMLEventReaderWrapper.java b/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/XMLEventReaderWrapper.java
new file mode 100644
index 0000000..efd2b07
--- /dev/null
+++ b/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/XMLEventReaderWrapper.java
@@ -0,0 +1,144 @@
+/**
+ * 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 com.msopentech.odatajclient.testservice.utils;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.XMLEvent;
+import org.apache.commons.io.IOUtils;
+
+public class XMLEventReaderWrapper implements XMLEventReader {
+
+ public final static String CONTENT = "CONTENT_TAG";
+
+ public final static String CONTENT_STAG = "<" + CONTENT + ">";
+
+ public final static String CONTENT_ETAG = "</" + CONTENT + ">";
+
+ private final XMLEventReader wrapped;
+
+ private XMLEvent nextGivenEvent = null;
+
+ public XMLEventReaderWrapper(final InputStream stream) throws Exception {
+ final XMLInputFactory factory = XMLInputFactory.newInstance();
+ factory.setProperty(XMLInputFactory.IS_VALIDATING, false);
+ factory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, false);
+
+
+ this.wrapped = factory.createXMLEventReader(
+ new ByteArrayInputStream(
+ (XMLEventReaderWrapper.CONTENT_STAG
+ + IOUtils.toString(stream)
+ + XMLEventReaderWrapper.CONTENT_ETAG).getBytes()));
+
+ init(wrapped);
+ }
+
+ public XMLEventReaderWrapper(final XMLEventReader wrapped) {
+ this.wrapped = wrapped;
+ init(wrapped);
+ }
+
+ private void init(final XMLEventReader wrapped) {
+
+ try {
+ this.nextGivenEvent = this.wrapped.nextEvent();
+
+ if (this.nextGivenEvent.isStartDocument()) {
+ this.nextGivenEvent = this.wrapped.nextEvent(); // discard start document
+ }
+
+ if (this.nextGivenEvent.isStartElement()
+ && CONTENT.equals(this.nextGivenEvent.asStartElement().getName().getLocalPart())) {
+ this.nextGivenEvent = this.wrapped.nextEvent(); // discard content start tag
+ }
+
+ } catch (Exception ignore) {
+ // ignore
+ }
+ }
+
+ @Override
+ public XMLEvent nextEvent() throws XMLStreamException {
+ final XMLEvent event = nextGivenEvent;
+
+ if (!isValidEvent(event)) {
+ throw new IllegalStateException("No event found");
+ }
+
+ nextGivenEvent = wrapped.hasNext() ? wrapped.nextEvent() : null;
+
+ return event;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return isValidEvent(nextGivenEvent);
+ }
+
+ @Override
+ public XMLEvent peek() throws XMLStreamException {
+ return wrapped.peek();
+ }
+
+ @Override
+ public String getElementText() throws XMLStreamException {
+ return wrapped.getElementText();
+ }
+
+ @Override
+ public XMLEvent nextTag() throws XMLStreamException {
+ XMLEvent tagEvent = wrapped.nextTag();
+ if (isValidEvent(tagEvent)) {
+ return tagEvent;
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public Object getProperty(final String string) throws IllegalArgumentException {
+ return wrapped.getProperty(string);
+ }
+
+ @Override
+ public void close() throws XMLStreamException {
+ wrapped.close();
+ }
+
+ @Override
+ public Object next() {
+ return wrapped.next();
+ }
+
+ @Override
+ public void remove() {
+ wrapped.remove();
+ }
+
+ private boolean isValidEvent(final XMLEvent event) {
+ // discard content end element tag ...
+ return event != null
+ && (!event.isEndElement()
+ || !CONTENT.equals(event.asEndElement().getName().getLocalPart()));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/a9f74a87/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/XMLUtilities.java
----------------------------------------------------------------------
diff --git a/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/XMLUtilities.java b/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/XMLUtilities.java
index 5d92317..65164b0 100644
--- a/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/XMLUtilities.java
+++ b/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/XMLUtilities.java
@@ -24,12 +24,15 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
+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;
@@ -247,7 +250,7 @@ public class XMLUtilities extends AbstractUtilities {
final XMLEventReader reader,
final XMLEventWriter discarded,
final String name,
- final List<Map.Entry<String, String>> filterAttrs)
+ final Collection<Map.Entry<String, String>> filterAttrs)
throws Exception {
return getAtomElement(reader, discarded, name, filterAttrs, 0, -1, -1, false).getValue();
}
@@ -256,7 +259,7 @@ public class XMLUtilities extends AbstractUtilities {
final XMLEventReader reader,
final XMLEventWriter discarded,
final String name,
- final List<Map.Entry<String, String>> filterAttrs,
+ final Collection<Map.Entry<String, String>> filterAttrs,
final int initialDepth,
final int minDepth,
final int maxDepth,
@@ -272,7 +275,7 @@ public class XMLUtilities extends AbstractUtilities {
if (event.getEventType() == XMLStreamConstants.START_ELEMENT) {
depth++;
- if (name.trim().equals(event.asStartElement().getName().getLocalPart())
+ if ((StringUtils.isBlank(name) || name.trim().equals(event.asStartElement().getName().getLocalPart()))
&& (minDepth < 0 || minDepth <= depth) && (maxDepth < 0 || maxDepth >= depth)) {
boolean match = filterAttrs == null || filterAttrs.isEmpty() || !filterInOr;
@@ -310,8 +313,7 @@ public class XMLUtilities extends AbstractUtilities {
throw new Exception(String.format("Could not find an element named '%s'", name));
}
- return new AbstractMap.SimpleEntry<Integer, XmlElement>(
- Integer.valueOf(depth - 1), getAtomElement(start, reader));
+ return new SimpleEntry<Integer, XmlElement>(Integer.valueOf(depth - 1), getAtomElement(start, reader));
}
public static XmlElement getAtomElement(
@@ -789,7 +791,8 @@ public class XMLUtilities extends AbstractUtilities {
}
@Override
- public InputStream readEntities(final List<String> links, final String linkName, final String next)
+ public InputStream readEntities(
+ final List<String> links, final String linkName, final String next, final boolean forceFeed)
throws Exception {
if (links.isEmpty()) {
@@ -798,7 +801,7 @@ public class XMLUtilities extends AbstractUtilities {
final ByteArrayOutputStream bos = new ByteArrayOutputStream();
- if (links.size() > 1) {
+ if (forceFeed || links.size() > 1) {
// build a feed
bos.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>".getBytes());
@@ -824,7 +827,7 @@ public class XMLUtilities extends AbstractUtilities {
IOUtils.copy(entry.toStream(), bos);
}
- if (links.size() > 1) {
+ if (forceFeed || links.size() > 1) {
if (StringUtils.isNotBlank(next)) {
bos.write(String.format("<link rel=\"next\" href=\"%s\" />", next).getBytes());
@@ -837,6 +840,161 @@ public class XMLUtilities extends AbstractUtilities {
}
@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 =
+ getAtomElement(reader, null, PROPERTIES, null, 0, 2, 3, false);
+ reader.close();
+
+ reader = propertyElement.getValue().getContentReader();
+
+ try {
+ while (true) {
+ final XmlElement property = getAtomElement(reader, null, null);
+ 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 =
+ getAtomElement(reader, null, LINK, null, pos, 2, 2, false);
+
+ 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();
+ final XMLOutputFactory xof = XMLOutputFactory.newInstance();
+ XMLEventWriter writer = xof.createXMLEventWriter(bos);
+
+ // ---------------------------------
+ // add property changes
+ // ---------------------------------
+ Map.Entry<Integer, XmlElement> propertyElement =
+ getAtomElement(reader, writer, PROPERTIES, null, 0, 2, 3, false);
+
+ writer.flush();
+
+ ByteArrayOutputStream pbos = new ByteArrayOutputStream();
+ OutputStreamWriter pwriter = new OutputStreamWriter(pbos);
+
+ final XMLEventReader propertyReader = propertyElement.getValue().getContentReader();
+
+ try {
+ while (true) {
+ final XmlElement property = getAtomElement(propertyReader, null, null);
+ 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
+ // ---------------------------------
+ reader = getEventReader(new ByteArrayInputStream(bos.toByteArray()));
+
+ bos.reset();
+ writer = xof.createXMLEventWriter(bos);
+
+ propertyElement = getAtomElement(reader, writer, CONTENT, null, 0, 2, 2, false);
+ 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 {
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/a9f74a87/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/XmlElement.java
----------------------------------------------------------------------
diff --git a/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/XmlElement.java b/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/XmlElement.java
index dc0d755..6b7220e 100644
--- a/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/XmlElement.java
+++ b/ODataJClient/test-service/src/main/java/com/msopentech/odatajclient/testservice/utils/XmlElement.java
@@ -24,11 +24,9 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import javax.xml.stream.XMLEventReader;
-import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement;
-import javax.xml.stream.events.XMLEvent;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -40,12 +38,6 @@ public class XmlElement {
*/
protected static final Logger LOG = LoggerFactory.getLogger(XmlElement.class);
- private final static String CONTENT = "CONTENT_TAG";
-
- private final static String CONTENT_STAG = "<" + CONTENT + ">";
-
- private final static String CONTENT_ETAG = "</" + CONTENT + ">";
-
private StartElement start;
private EndElement end;
@@ -73,15 +65,7 @@ public class XmlElement {
}
public XMLEventReader getContentReader() throws Exception {
- final XMLInputFactory factory = XMLInputFactory.newInstance();
- factory.setProperty(XMLInputFactory.IS_VALIDATING, false);
- factory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, false);
-
-
- final XMLEventReader contentReader = factory.createXMLEventReader(
- new ByteArrayInputStream((CONTENT_STAG + IOUtils.toString(getContent()) + CONTENT_ETAG).getBytes()));
-
- return new XMLEventReaderWrapper(contentReader);
+ return new XMLEventReaderWrapper(getContent());
}
public void setContent(final InputStream content) throws IOException {
@@ -90,98 +74,6 @@ public class XmlElement {
content.close();
}
- private class XMLEventReaderWrapper implements XMLEventReader {
-
- private final XMLEventReader wrapped;
-
- private XMLEvent nextGivenEvent = null;
-
- public XMLEventReaderWrapper(XMLEventReader wrapped) {
- this.wrapped = wrapped;
-
- try {
- this.nextGivenEvent = this.wrapped.nextEvent();
-
- if (this.nextGivenEvent.isStartDocument()) {
- this.nextGivenEvent = this.wrapped.nextEvent(); // discard start document
- }
-
- if (this.nextGivenEvent.isStartElement()
- && CONTENT.equals(this.nextGivenEvent.asStartElement().getName().getLocalPart())) {
- this.nextGivenEvent = this.wrapped.nextEvent(); // discard content start tag
- }
-
- } catch (Exception ignore) {
- // ignore
- }
- }
-
- @Override
- public XMLEvent nextEvent() throws XMLStreamException {
- final XMLEvent event = nextGivenEvent;
-
- if (!isValidEvent(event)) {
- throw new IllegalStateException("No event found");
- }
-
- nextGivenEvent = wrapped.hasNext() ? wrapped.nextEvent() : null;
-
- return event;
- }
-
- @Override
- public boolean hasNext() {
- return isValidEvent(nextGivenEvent);
- }
-
- @Override
- public XMLEvent peek() throws XMLStreamException {
- return wrapped.peek();
- }
-
- @Override
- public String getElementText() throws XMLStreamException {
- return wrapped.getElementText();
- }
-
- @Override
- public XMLEvent nextTag() throws XMLStreamException {
- XMLEvent tagEvent = wrapped.nextTag();
- if (isValidEvent(tagEvent)) {
- return tagEvent;
- } else {
- return null;
- }
- }
-
- @Override
- public Object getProperty(final String string) throws IllegalArgumentException {
- return wrapped.getProperty(string);
- }
-
- @Override
- public void close() throws XMLStreamException {
- wrapped.close();
- }
-
- @Override
- public Object next() {
- return wrapped.next();
- }
-
- @Override
- public void remove() {
- wrapped.remove();
- }
-
- private boolean isValidEvent(final XMLEvent event) {
- // discard content end element tag ...
- return event != null
- && (!event.isEndElement()
- || !CONTENT.equals(event.asEndElement().getName().getLocalPart()));
- }
- }
-
public InputStream toStream() throws Exception {
InputStream res;
try {
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/a9f74a87/ODataJClient/test-service/src/main/resources/v3/Product/-10/entity.full.json
----------------------------------------------------------------------
diff --git a/ODataJClient/test-service/src/main/resources/v3/Product/-10/entity.full.json b/ODataJClient/test-service/src/main/resources/v3/Product/-10/entity.full.json
index 5a486e8..33ed9d3 100644
--- a/ODataJClient/test-service/src/main/resources/v3/Product/-10/entity.full.json
+++ b/ODataJClient/test-service/src/main/resources/v3/Product/-10/entity.full.json
@@ -2,7 +2,7 @@
"odata.metadata": "http://localhost:${cargo.servlet.port}/StaticService/V3/Static.svc/$metadata#Product/@Element",
"odata.type": "Microsoft.Test.OData.Services.AstoriaDefaultService.Product",
"odata.id": "http://localhost:${cargo.servlet.port}/StaticService/V3/Static.svc/Product(-10)",
- "odata.etag": "W/\"'New%20BaseConcurrency(1392649542502)'\"",
+ "odata.etag": "W/\"'assrfsssfdtrmdajadchvrqehsszybuiyiu%C3%9Flhmazsuemptziruotkqcy%C3%9F%C3%9Fp'\"",
"odata.editLink": "Product(-10)",
"RelatedProducts@odata.navigationLinkUrl": "Product(-10)/RelatedProducts",
"Detail@odata.navigationLinkUrl": "Product(-10)/Detail",
@@ -15,9 +15,37 @@
},
"Picture@odata.mediaEditLink": "Product(-10)/Picture",
"ProductId": -10,
- "Description": "New Description(1391427672964)",
- "Dimensions": null,
- "BaseConcurrency": "New BaseConcurrency(1391427673066)",
- "ComplexConcurrency": null,
- "NestedComplexConcurrency": null
+ "Description": "onesusjnzuzrmzhqankkugdrftiukzkzqaggsfdmtvineulehkrbpu",
+ "Dimensions":
+ {
+ "odata.type": "Microsoft.Test.OData.Services.AstoriaDefaultService.Dimensions",
+ "Width@odata.type": "Edm.Decimal",
+ "Width": "-79228162514264337593543950335",
+ "Height@odata.type": "Edm.Decimal",
+ "Height": "-0.492988348718789",
+ "Depth@odata.type": "Edm.Decimal",
+ "Depth": "-78702059456772700000000000000"
+ },
+ "BaseConcurrency": "assrfsssfdtrmdajadchvrqehsszybuiyiußlhmazsuemptziruotkqcyßßp",
+ "ComplexConcurrency":
+ {
+ "odata.type": "Microsoft.Test.OData.Services.AstoriaDefaultService.ConcurrencyInfo",
+ "Token": null,
+ "QueriedDateTime@odata.type": "Edm.DateTime",
+ "QueriedDateTime": "2013-01-10T06:27:51.1667673"
+ },
+ "NestedComplexConcurrency":
+ {
+ "odata.type": "Microsoft.Test.OData.Services.AstoriaDefaultService.AuditInfo",
+ "ModifiedDate@odata.type": "Edm.DateTime",
+ "ModifiedDate": "9999-12-31T23:59:59.9999999",
+ "ModifiedBy": "gsrqilravbargkknoljssfn",
+ "Concurrency":
+ {
+ "odata.type": "Microsoft.Test.OData.Services.AstoriaDefaultService.ConcurrencyInfo",
+ "Token": "び欲ぜぞボゾそaチぼ縷ソ黑ミ",
+ "QueriedDateTime@odata.type": "Edm.DateTime",
+ "QueriedDateTime": "2011-09-01T06:31:58.336924"
+ }
+ }
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/a9f74a87/ODataJClient/test-service/src/main/resources/v3/Product/-10/entity.xml
----------------------------------------------------------------------
diff --git a/ODataJClient/test-service/src/main/resources/v3/Product/-10/entity.xml b/ODataJClient/test-service/src/main/resources/v3/Product/-10/entity.xml
index 0fed5d7..f5b6212 100644
--- a/ODataJClient/test-service/src/main/resources/v3/Product/-10/entity.xml
+++ b/ODataJClient/test-service/src/main/resources/v3/Product/-10/entity.xml
@@ -19,7 +19,7 @@
under the License.
-->
-<entry xml:base="http://localhost:${cargo.servlet.port}/StaticService/V3/Static.svc/" 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" xmlns:georss="http://www.georss.org/georss" xmlns:gml="http://www.opengis.net/gml" m:etag="W/"'New%20BaseConcurrency(1392649542502)'"">
+<entry xml:base="http://localhost:${cargo.servlet.port}/StaticService/V3/Static.svc/" 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" xmlns:georss="http://www.georss.org/georss" xmlns:gml="http://www.opengis.net/gml" m:etag="W/"'assrfsssfdtrmdajadchvrqehsszybuiyiu%C3%9Flhmazsuemptziruotkqcy%C3%9F%C3%9Fp'"">
<id>http://localhost:${cargo.servlet.port}/StaticService/V3/Static.svc/Product(-10)</id>
<category term="Microsoft.Test.OData.Services.AstoriaDefaultService.Product" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<link rel="edit" title="Product" href="Product(-10)" />
@@ -28,7 +28,7 @@
<link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Reviews" type="application/atom+xml;type=feed" title="Reviews" href="Product(-10)/Reviews" />
<link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Photos" type="application/atom+xml;type=feed" title="Photos" href="Product(-10)/Photos" />
<title />
- <updated>2014-02-17T14:43:42Z</updated>
+ <updated>2014-03-08T16:39:47Z</updated>
<author>
<name />
</author>
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/a9f74a87/ODataJClient/test-service/src/main/resources/v3/Product/-10/etag.txt
----------------------------------------------------------------------
diff --git a/ODataJClient/test-service/src/main/resources/v3/Product/-10/etag.txt b/ODataJClient/test-service/src/main/resources/v3/Product/-10/etag.txt
index 0af74cf..e1f788c 100644
--- a/ODataJClient/test-service/src/main/resources/v3/Product/-10/etag.txt
+++ b/ODataJClient/test-service/src/main/resources/v3/Product/-10/etag.txt
@@ -1 +1 @@
-W/"'New%20BaseConcurrency(1392649542502)'"
\ No newline at end of file
+W/"'assrfsssfdtrmdajadchvrqehsszybuiyiu%C3%9Flhmazsuemptziruotkqcy%C3%9F%C3%9Fp'"
\ No newline at end of file