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/04/15 16:33:32 UTC
git commit: [OLINGO-246] provided batch integration;
still missing internak batch reference support
Repository: olingo-odata4
Updated Branches:
refs/heads/master 542541dd4 -> 68f27d57a
[OLINGO-246] provided batch integration; still missing internak batch reference support
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/68f27d57
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/68f27d57
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/68f27d57
Branch: refs/heads/master
Commit: 68f27d57a1d7dc10b1382f3b44b327ce052bc0b6
Parents: 542541d
Author: fmartelli <fa...@gmail.com>
Authored: Tue Apr 15 16:33:19 2014 +0200
Committer: fmartelli <fa...@gmail.com>
Committed: Tue Apr 15 16:33:19 2014 +0200
----------------------------------------------------------------------
.../org/apache/olingo/fit/AbstractServices.java | 235 +++++-
.../olingo/fit/utils/AbstractUtilities.java | 22 +
.../org/apache/olingo/fit/utils/Constants.java | 5 +
.../api/communication/header/HeaderName.java | 2 +-
.../request/cud/ODataEntityCreateRequest.java | 3 +-
.../request/cud/ODataEntityUpdateRequest.java | 3 +-
.../request/retrieve/ODataRetrieveRequest.java | 4 +-
.../request/batch/ODataBatchRequestImpl.java | 5 +-
.../request/batch/ODataBatchUtilities.java | 3 +-
.../cud/ODataEntityCreateRequestImpl.java | 3 +-
.../cud/ODataEntityUpdateRequestImpl.java | 4 +-
.../retrieve/AbstractODataRetrieveRequest.java | 3 +-
.../client/core/it/v3/BatchTestITCase.java | 806 ++++++++++---------
13 files changed, 688 insertions(+), 410 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/68f27d57/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 00e22f3..4f9d970 100644
--- a/fit/src/main/java/org/apache/olingo/fit/AbstractServices.java
+++ b/fit/src/main/java/org/apache/olingo/fit/AbstractServices.java
@@ -18,12 +18,12 @@
*/
package org.apache.olingo.fit;
-import org.apache.olingo.commons.api.data.Container;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.JsonNode;
import org.apache.olingo.commons.api.data.Feed;
import org.apache.olingo.commons.api.data.Link;
import org.apache.olingo.commons.api.data.Property;
import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
-import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.commons.core.data.AtomFeedImpl;
import org.apache.olingo.commons.core.data.LinkImpl;
import org.apache.olingo.fit.metadata.Metadata;
@@ -33,24 +33,28 @@ import org.apache.olingo.fit.utils.ConstantKey;
import org.apache.olingo.fit.utils.Constants;
import org.apache.olingo.fit.utils.DataBinder;
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
+import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.util.AbstractMap;
import java.util.Arrays;
import java.util.Collections;
+import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import javax.mail.Header;
+import javax.mail.internet.MimeBodyPart;
+import javax.mail.internet.MimeMultipart;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
@@ -65,12 +69,20 @@ import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedHashMap;
+import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.cxf.jaxrs.ext.multipart.Attachment;
+import org.apache.cxf.jaxrs.ext.multipart.Multipart;
+import org.apache.cxf.jaxrs.ext.multipart.MultipartBody;
+import org.apache.olingo.commons.api.data.Container;
import org.apache.olingo.commons.api.data.Entry;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
+import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.commons.core.data.AtomEntryImpl;
import org.apache.olingo.commons.core.data.AtomPropertyImpl;
import org.apache.olingo.commons.core.data.AtomSerializer;
@@ -81,13 +93,13 @@ import org.apache.olingo.commons.core.data.PrimitiveValueImpl;
import org.apache.olingo.fit.metadata.EntitySet;
import org.apache.olingo.fit.metadata.EntityType;
import org.apache.olingo.fit.metadata.NavigationProperty;
+import org.apache.olingo.fit.methods.MERGE;
+import org.apache.olingo.fit.methods.PATCH;
+import org.apache.olingo.fit.serializer.FITAtomDeserializer;
import org.apache.olingo.fit.utils.Accept;
import org.apache.olingo.fit.utils.FSManager;
import org.apache.olingo.fit.utils.Commons;
-import org.apache.olingo.fit.methods.MERGE;
-import org.apache.olingo.fit.methods.PATCH;
-import org.apache.olingo.fit.serializer.FITAtomDeserializer;
import org.apache.olingo.fit.utils.AbstractJSONUtilities;
import org.apache.olingo.fit.utils.AbstractUtilities;
import org.apache.olingo.fit.utils.AbstractXMLUtilities;
@@ -102,6 +114,10 @@ public abstract class AbstractServices {
*/
protected static final Logger LOG = LoggerFactory.getLogger(AbstractServices.class);
+ private Pattern requestPatter = Pattern.compile("(.*) (http://.*) HTTP/.*");
+
+ private static final String boundary = "batch_243234_25424_ef_892u748";
+
protected final ODataServiceVersion version;
protected final AbstractXMLUtilities xml;
@@ -174,6 +190,197 @@ public abstract class AbstractServices {
}
}
+ @POST
+ @Path("/$batch")
+ @Consumes("multipart/mixed")
+ @Produces("application/octet-stream; boundary=" + boundary)
+ public Response batch(final @Multipart MultipartBody attachment) {
+ try {
+ return xml.createBatchResponse(exploreMultipart(attachment.getAllAttachments(), boundary), boundary);
+ } catch (IOException e) {
+ return xml.createFaultResponse(Accept.XML.toString(version), e);
+ }
+ }
+
+ private Response bodyPartRequest(final MimeBodyPart body) throws Exception {
+
+ @SuppressWarnings("unchecked")
+ final Enumeration<Header> en = (Enumeration<Header>) body.getAllHeaders();
+
+ Header header = en.nextElement();
+ final String request = header.getName() + ":" + header.getValue();
+ final Matcher matcher = requestPatter.matcher(request);
+
+ if (matcher.find()) {
+ final MultivaluedMap<String, String> headers = new MultivaluedHashMap<String, String>();
+
+ while (en.hasMoreElements()) {
+ header = en.nextElement();
+ headers.putSingle(header.getName(), header.getValue());
+ }
+
+ String method = matcher.group(1);
+ if ("PATCH".equals(method) || "MERGE".equals(method)) {
+ headers.putSingle("X-HTTP-METHOD", method);
+ method = "POST";
+ }
+
+ final String url = matcher.group(2);
+
+ final WebClient client = WebClient.create(url);
+
+ client.headers(headers);
+
+ return client.invoke(method, body.getDataHandler().getInputStream());
+ } else {
+ return null;
+ }
+ }
+
+ public InputStream exploreMultipart(final List<Attachment> attachments, final String boundary) throws IOException {
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+ Response res = null;
+ try {
+ for (Attachment obj : attachments) {
+ bos.write(("--" + boundary).getBytes());
+ bos.write(Constants.CRLF);
+
+ final Object content = obj.getDataHandler().getContent();
+ if (content instanceof MimeMultipart) {
+ final String cboundary = "changeset_" + UUID.randomUUID().toString();
+ bos.write(("Content-Type: multipart/mixed;boundary=" + cboundary).getBytes());
+ bos.write(Constants.CRLF);
+ bos.write(Constants.CRLF);
+
+ final ByteArrayOutputStream chbos = new ByteArrayOutputStream();
+ String lastContebtID = null;
+ try {
+ for (int i = 0; i < ((MimeMultipart) content).getCount(); i++) {
+ final MimeBodyPart part = (MimeBodyPart) ((MimeMultipart) content).getBodyPart(i);
+ lastContebtID = part.getContentID();
+ addChangesetItemIntro(chbos, lastContebtID, cboundary);
+
+ res = bodyPartRequest(new MimeBodyPart(part.getInputStream()));
+ if (res.getStatus() > 400) {
+ throw new Exception("Failure processing changeset");
+ }
+
+ addSingleBatchResponse(res, lastContebtID, chbos);
+ }
+ bos.write(chbos.toByteArray());
+ IOUtils.closeQuietly(chbos);
+
+ bos.write(("--" + cboundary + "--").getBytes());
+ bos.write(Constants.CRLF);
+ } catch (Exception e) {
+ LOG.warn("While processing changeset", e);
+ IOUtils.closeQuietly(chbos);
+
+ addChangesetItemIntro(bos, lastContebtID, cboundary);
+ if (res == null || res.getStatus() < 400) {
+ addErrorBatchResponse(e, "1", bos);
+ } else {
+ addSingleBatchResponse(res, lastContebtID, bos);
+ }
+
+ bos.write(("--" + cboundary + "--").getBytes());
+ bos.write(Constants.CRLF);
+ }
+ } else {
+ addItemIntro(bos);
+
+ res = bodyPartRequest(new MimeBodyPart(obj.getDataHandler().getInputStream()));
+
+ if (res.getStatus() > 400) {
+ throw new Exception("Failure processing changeset");
+ }
+
+ addSingleBatchResponse(res, bos);
+ }
+ }
+ } catch (Exception e) {
+ if (res == null || res.getStatus() < 400) {
+ addErrorBatchResponse(e, bos);
+ } else {
+ addSingleBatchResponse(res, bos);
+ }
+ }
+
+ bos.write(("--" + boundary + "--").getBytes());
+
+ return new ByteArrayInputStream(bos.toByteArray());
+ }
+
+ private void addItemIntro(final ByteArrayOutputStream bos) throws IOException {
+ bos.write("Content-Type: application/http".getBytes());
+ bos.write(Constants.CRLF);
+ bos.write("Content-Transfer-Encoding: binary".getBytes());
+ bos.write(Constants.CRLF);
+ bos.write(Constants.CRLF);
+ }
+
+ private void addChangesetItemIntro(
+ final ByteArrayOutputStream bos, final String contentId, final String cboundary) throws IOException {
+ bos.write(("--" + cboundary).getBytes());
+ bos.write(Constants.CRLF);
+ bos.write(("Content-ID: " + contentId).getBytes());
+ bos.write(Constants.CRLF);
+ addItemIntro(bos);
+ }
+
+ private void addSingleBatchResponse(
+ final Response response, final ByteArrayOutputStream bos) throws IOException {
+ addSingleBatchResponse(response, null, bos);
+ }
+
+ private void addSingleBatchResponse(
+ final Response response, final String contentId, final ByteArrayOutputStream bos) throws IOException {
+ bos.write("HTTP/1.1 ".getBytes());
+ bos.write(String.valueOf(response.getStatusInfo().getStatusCode()).getBytes());
+ bos.write(" ".getBytes());
+ bos.write(response.getStatusInfo().getReasonPhrase().getBytes());
+ bos.write(Constants.CRLF);
+
+ for (Map.Entry<String, List<Object>> header : response.getHeaders().entrySet()) {
+ StringBuilder builder = new StringBuilder();
+ for (Object value : header.getValue()) {
+ if (builder.length() > 0) {
+ builder.append(", ");
+ }
+ builder.append(value.toString());
+ }
+ builder.insert(0, ": ").insert(0, header.getKey());
+ bos.write(builder.toString().getBytes());
+ bos.write(Constants.CRLF);
+ }
+
+ if (StringUtils.isNotBlank(contentId)) {
+ bos.write(("Content-ID: " + contentId).getBytes());
+ bos.write(Constants.CRLF);
+ }
+
+ bos.write(Constants.CRLF);
+
+ final Object entity = response.getEntity();
+ if (entity != null) {
+ bos.write(IOUtils.toByteArray((InputStream) entity));
+ bos.write(Constants.CRLF);
+ }
+
+ bos.write(Constants.CRLF);
+ }
+
+ private void addErrorBatchResponse(final Exception e, final ByteArrayOutputStream bos)
+ throws IOException {
+ addErrorBatchResponse(e, null, bos);
+ }
+
+ private void addErrorBatchResponse(final Exception e, final String contentId, final ByteArrayOutputStream bos)
+ throws IOException {
+ addSingleBatchResponse(xml.createFaultResponse(Accept.XML.toString(version), e), contentId, bos);
+ }
+
@MERGE
@Path("/{entitySetName}({entityId})")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON})
@@ -386,7 +593,7 @@ public abstract class AbstractServices {
} else {
final Container<JSONEntryImpl> jcontainer =
mapper.readValue(IOUtils.toInputStream(entity), new TypeReference<JSONEntryImpl>() {
- });
+ });
entry = (new DataBinder(version)).
getAtomEntry(jcontainer.getObject());
@@ -459,13 +666,13 @@ public abstract class AbstractServices {
replaceAll("\"Salary\":[0-9]*,", "\"Salary\":0,").
replaceAll("\"Title\":\".*\"", "\"Title\":\"[Sacked]\"").
replaceAll("\\<d:Salary m:type=\"Edm.Int32\"\\>.*\\</d:Salary\\>",
- "<d:Salary m:type=\"Edm.Int32\">0</d:Salary>").
+ "<d:Salary m:type=\"Edm.Int32\">0</d:Salary>").
replaceAll("\\<d:Title\\>.*\\</d:Title\\>", "<d:Title>[Sacked]</d:Title>");
final FSManager fsManager = FSManager.instance(version);
fsManager.putInMemory(IOUtils.toInputStream(newContent, "UTF-8"),
fsManager.getAbsolutePath(Commons.getEntityBasePath("Person", entityId) + Constants.get(version,
- ConstantKey.ENTITY), utils.getKey()));
+ ConstantKey.ENTITY), utils.getKey()));
return utils.getValue().createResponse(null, null, utils.getKey(), Response.Status.NO_CONTENT);
} catch (Exception e) {
@@ -517,9 +724,9 @@ public abstract class AbstractServices {
final Long newSalary = Long.valueOf(salaryMatcher.group(1)) + n;
newContent = newContent.
replaceAll("\"Salary\":" + salaryMatcher.group(1) + ",",
- "\"Salary\":" + newSalary + ",").
+ "\"Salary\":" + newSalary + ",").
replaceAll("\\<d:Salary m:type=\"Edm.Int32\"\\>" + salaryMatcher.group(1) + "</d:Salary\\>",
- "<d:Salary m:type=\"Edm.Int32\">" + newSalary + "</d:Salary>");
+ "<d:Salary m:type=\"Edm.Int32\">" + newSalary + "</d:Salary>");
}
FSManager.instance(version).putInMemory(IOUtils.toInputStream(newContent, "UTF-8"),
@@ -651,7 +858,7 @@ public abstract class AbstractServices {
mapper.writeValue(
writer, new JsonFeedContainer<JSONFeedImpl>(container.getContextURL(), container.getMetadataETag(),
- new DataBinder(version).getJsonFeed(container.getObject())));
+ new DataBinder(version).getJsonFeed(container.getObject())));
}
return xml.createResponse(new ByteArrayInputStream(content.toByteArray()),
@@ -833,7 +1040,7 @@ public abstract class AbstractServices {
final ObjectMapper mapper = Commons.getJsonMapper(version);
mapper.writeValue(
writer, new JsonEntryContainer<JSONEntryImpl>(container.getContextURL(), container.getMetadataETag(),
- (new DataBinder(version)).getJsonEntry((AtomEntryImpl) container.getObject())));
+ (new DataBinder(version)).getJsonEntry((AtomEntryImpl) container.getObject())));
}
return xml.createResponse(new ByteArrayInputStream(content.toByteArray()),
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/68f27d57/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 9c0ef94..8ef4472 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
@@ -60,6 +60,21 @@ public abstract class AbstractUtilities {
protected final static Pattern entityUriPattern = Pattern.compile(".*\\/.*\\(.*\\)");
+ /**
+ * Batch/Changeset content type.
+ */
+ public static final String MULTIPART_CONTENT_TYPE = "multipart/mixed";
+
+ /**
+ * Batch item content type.
+ */
+ public static final String ITEM_CONTENT_TYPE = "application/http";
+
+ /**
+ * Boundary key.
+ */
+ public static final String BOUNDARY = "boundary";
+
public AbstractUtilities(final ODataServiceVersion version) throws Exception {
this.version = version;
this.fsManager = FSManager.instance(version);
@@ -399,6 +414,13 @@ public abstract class AbstractUtilities {
return createResponse(entity, etag, accept, null);
}
+ public Response createBatchResponse(final InputStream stream, final String boundary) {
+
+ final Response.ResponseBuilder builder = Response.accepted(stream);
+ builder.header(Constants.get(version, ConstantKey.ODATA_SERVICE_VERSION), version.toString() + ";");
+ return builder.build();
+ }
+
public Response createResponse(
final InputStream entity, final String etag, final Accept accept, final Response.Status status) {
final Response.ResponseBuilder builder = Response.ok();
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/68f27d57/fit/src/main/java/org/apache/olingo/fit/utils/Constants.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/utils/Constants.java b/fit/src/main/java/org/apache/olingo/fit/utils/Constants.java
index 5066cb0..975a537 100644
--- a/fit/src/main/java/org/apache/olingo/fit/utils/Constants.java
+++ b/fit/src/main/java/org/apache/olingo/fit/utils/Constants.java
@@ -29,6 +29,11 @@ public class Constants {
private final static Map<ConstantKey, String> constants = new EnumMap<ConstantKey, String>(ConstantKey.class);
+ /**
+ * CR/LF.
+ */
+ public static final byte[] CRLF = {13, 10};
+
public static Charset encoding = Charset.forName("UTF-8");
static {
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/68f27d57/lib/client-api/src/main/java/org/apache/olingo/client/api/communication/header/HeaderName.java
----------------------------------------------------------------------
diff --git a/lib/client-api/src/main/java/org/apache/olingo/client/api/communication/header/HeaderName.java b/lib/client-api/src/main/java/org/apache/olingo/client/api/communication/header/HeaderName.java
index 67b3043..a99c5ef 100644
--- a/lib/client-api/src/main/java/org/apache/olingo/client/api/communication/header/HeaderName.java
+++ b/lib/client-api/src/main/java/org/apache/olingo/client/api/communication/header/HeaderName.java
@@ -59,7 +59,7 @@ public enum HeaderName {
* <li>multipart/mixed</li>
* </ul>
*/
- contentType("Content-Type", Arrays.asList(ODataServiceVersion.V30)),
+ contentType("Content-Type", Arrays.asList(ODataServiceVersion.V30, ODataServiceVersion.V40)),
/**
* This header is a custom HTTP header defined for protocol versioning purposes. This header MAY be present on any
* request or response message.
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/68f27d57/lib/client-api/src/main/java/org/apache/olingo/client/api/communication/request/cud/ODataEntityCreateRequest.java
----------------------------------------------------------------------
diff --git a/lib/client-api/src/main/java/org/apache/olingo/client/api/communication/request/cud/ODataEntityCreateRequest.java b/lib/client-api/src/main/java/org/apache/olingo/client/api/communication/request/cud/ODataEntityCreateRequest.java
index 73471b9..ddd5975 100644
--- a/lib/client-api/src/main/java/org/apache/olingo/client/api/communication/request/cud/ODataEntityCreateRequest.java
+++ b/lib/client-api/src/main/java/org/apache/olingo/client/api/communication/request/cud/ODataEntityCreateRequest.java
@@ -19,6 +19,7 @@
package org.apache.olingo.client.api.communication.request.cud;
import org.apache.olingo.client.api.communication.request.ODataBasicRequest;
+import org.apache.olingo.client.api.communication.request.ODataBatchableRequest;
import org.apache.olingo.client.api.communication.response.ODataEntityCreateResponse;
import org.apache.olingo.commons.api.domain.CommonODataEntity;
import org.apache.olingo.commons.api.format.ODataPubFormat;
@@ -29,5 +30,5 @@ import org.apache.olingo.commons.api.format.ODataPubFormat;
* @param <E> concrete ODataEntity implementation
*/
public interface ODataEntityCreateRequest<E extends CommonODataEntity>
- extends ODataBasicRequest<ODataEntityCreateResponse<E>, ODataPubFormat> {
+ extends ODataBasicRequest<ODataEntityCreateResponse<E>, ODataPubFormat>, ODataBatchableRequest {
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/68f27d57/lib/client-api/src/main/java/org/apache/olingo/client/api/communication/request/cud/ODataEntityUpdateRequest.java
----------------------------------------------------------------------
diff --git a/lib/client-api/src/main/java/org/apache/olingo/client/api/communication/request/cud/ODataEntityUpdateRequest.java b/lib/client-api/src/main/java/org/apache/olingo/client/api/communication/request/cud/ODataEntityUpdateRequest.java
index 3f02897..341028e 100644
--- a/lib/client-api/src/main/java/org/apache/olingo/client/api/communication/request/cud/ODataEntityUpdateRequest.java
+++ b/lib/client-api/src/main/java/org/apache/olingo/client/api/communication/request/cud/ODataEntityUpdateRequest.java
@@ -19,6 +19,7 @@
package org.apache.olingo.client.api.communication.request.cud;
import org.apache.olingo.client.api.communication.request.ODataBasicRequest;
+import org.apache.olingo.client.api.communication.request.ODataBatchableRequest;
import org.apache.olingo.client.api.communication.response.ODataEntityUpdateResponse;
import org.apache.olingo.commons.api.domain.CommonODataEntity;
import org.apache.olingo.commons.api.format.ODataPubFormat;
@@ -29,5 +30,5 @@ import org.apache.olingo.commons.api.format.ODataPubFormat;
* @param <E> concrete ODataEntity implementation
*/
public interface ODataEntityUpdateRequest<E extends CommonODataEntity>
- extends ODataBasicRequest<ODataEntityUpdateResponse<E>, ODataPubFormat> {
+ extends ODataBasicRequest<ODataEntityUpdateResponse<E>, ODataPubFormat>, ODataBatchableRequest {
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/68f27d57/lib/client-api/src/main/java/org/apache/olingo/client/api/communication/request/retrieve/ODataRetrieveRequest.java
----------------------------------------------------------------------
diff --git a/lib/client-api/src/main/java/org/apache/olingo/client/api/communication/request/retrieve/ODataRetrieveRequest.java b/lib/client-api/src/main/java/org/apache/olingo/client/api/communication/request/retrieve/ODataRetrieveRequest.java
index 073f520..61e505c 100644
--- a/lib/client-api/src/main/java/org/apache/olingo/client/api/communication/request/retrieve/ODataRetrieveRequest.java
+++ b/lib/client-api/src/main/java/org/apache/olingo/client/api/communication/request/retrieve/ODataRetrieveRequest.java
@@ -19,11 +19,13 @@
package org.apache.olingo.client.api.communication.request.retrieve;
import org.apache.olingo.client.api.communication.request.ODataBasicRequest;
+import org.apache.olingo.client.api.communication.request.ODataBatchableRequest;
import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse;
import org.apache.olingo.commons.api.format.Format;
/**
* This is an abstract representation of an OData retrieve query request returning one or more result item.
*/
-public interface ODataRetrieveRequest<V, T extends Format> extends ODataBasicRequest<ODataRetrieveResponse<V>, T> {
+public interface ODataRetrieveRequest<V, T extends Format>
+ extends ODataBasicRequest<ODataRetrieveResponse<V>, T>, ODataBatchableRequest {
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/68f27d57/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/batch/ODataBatchRequestImpl.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/batch/ODataBatchRequestImpl.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/batch/ODataBatchRequestImpl.java
index 9ebf783..165a514 100644
--- a/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/batch/ODataBatchRequestImpl.java
+++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/batch/ODataBatchRequestImpl.java
@@ -151,7 +151,8 @@ public class ODataBatchRequestImpl extends AbstractODataStreamedRequest<ODataBat
/**
* Batch request payload management.
*/
- public class BatchStreamManagerImpl extends AbstractODataStreamManager<ODataBatchResponse> {
+ public class BatchStreamManagerImpl extends AbstractODataStreamManager<ODataBatchResponse>
+ implements BatchStreamManager {
/**
* Batch request current item.
@@ -178,6 +179,7 @@ public class ODataBatchRequestImpl extends AbstractODataStreamedRequest<ODataBat
*
* @return ODataChangeset instance.
*/
+ @Override
public ODataChangeset addChangeset() {
closeCurrentItem();
@@ -197,6 +199,7 @@ public class ODataBatchRequestImpl extends AbstractODataStreamedRequest<ODataBat
*
* @return ODataRetrieve instance.
*/
+ @Override
public ODataRetrieve addRetrieve() {
closeCurrentItem();
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/68f27d57/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/batch/ODataBatchUtilities.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/batch/ODataBatchUtilities.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/batch/ODataBatchUtilities.java
index 7474e13..1fc6d7b 100644
--- a/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/batch/ODataBatchUtilities.java
+++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/batch/ODataBatchUtilities.java
@@ -148,8 +148,7 @@ public class ODataBatchUtilities {
}
} else {
- for (int i = 0;
- controller.isValidBatch() && controller.getBatchLineIterator().hasNext() && i < count; i++) {
+ for (int i = 0; controller.isValidBatch() && controller.getBatchLineIterator().hasNext() && i < count; i++) {
currentLine = controller.getBatchLineIterator().nextLine();
}
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/68f27d57/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/cud/ODataEntityCreateRequestImpl.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/cud/ODataEntityCreateRequestImpl.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/cud/ODataEntityCreateRequestImpl.java
index 18485ae..cfd9089 100644
--- a/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/cud/ODataEntityCreateRequestImpl.java
+++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/cud/ODataEntityCreateRequestImpl.java
@@ -25,7 +25,6 @@ import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.olingo.client.api.CommonODataClient;
-import org.apache.olingo.client.api.communication.request.ODataBatchableRequest;
import org.apache.olingo.client.api.communication.request.cud.ODataEntityCreateRequest;
import org.apache.olingo.client.api.communication.response.ODataEntityCreateResponse;
import org.apache.olingo.commons.api.domain.CommonODataEntity;
@@ -44,7 +43,7 @@ import org.apache.olingo.commons.api.data.Entry;
*/
public class ODataEntityCreateRequestImpl<E extends CommonODataEntity>
extends AbstractODataBasicRequest<ODataEntityCreateResponse<E>, ODataPubFormat>
- implements ODataEntityCreateRequest<E>, ODataBatchableRequest {
+ implements ODataEntityCreateRequest<E> {
/**
* Entity to be created.
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/68f27d57/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/cud/ODataEntityUpdateRequestImpl.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/cud/ODataEntityUpdateRequestImpl.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/cud/ODataEntityUpdateRequestImpl.java
index 9a84de3..67be0d4 100644
--- a/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/cud/ODataEntityUpdateRequestImpl.java
+++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/cud/ODataEntityUpdateRequestImpl.java
@@ -25,7 +25,6 @@ import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.olingo.client.api.CommonODataClient;
-import org.apache.olingo.client.api.communication.request.ODataBatchableRequest;
import org.apache.olingo.client.api.communication.request.cud.ODataEntityUpdateRequest;
import org.apache.olingo.client.api.communication.response.ODataEntityUpdateResponse;
import org.apache.olingo.commons.api.domain.CommonODataEntity;
@@ -39,11 +38,12 @@ import org.apache.olingo.commons.api.data.Entry;
/**
* This class implements an OData update request.
+ *
* @param <E> concrete ODataEntity implementation
*/
public class ODataEntityUpdateRequestImpl<E extends CommonODataEntity>
extends AbstractODataBasicRequest<ODataEntityUpdateResponse<E>, ODataPubFormat>
- implements ODataEntityUpdateRequest<E>, ODataBatchableRequest {
+ implements ODataEntityUpdateRequest<E> {
/**
* Changes to be applied.
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/68f27d57/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/retrieve/AbstractODataRetrieveRequest.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/retrieve/AbstractODataRetrieveRequest.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/retrieve/AbstractODataRetrieveRequest.java
index 53e46c1..f1ae24b 100644
--- a/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/retrieve/AbstractODataRetrieveRequest.java
+++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/retrieve/AbstractODataRetrieveRequest.java
@@ -23,7 +23,6 @@ import java.net.URI;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.olingo.client.api.CommonODataClient;
-import org.apache.olingo.client.api.communication.request.ODataBatchableRequest;
import org.apache.olingo.client.api.communication.request.retrieve.ODataRetrieveRequest;
import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse;
import org.apache.olingo.commons.api.format.Format;
@@ -36,7 +35,7 @@ import org.apache.olingo.client.core.communication.response.AbstractODataRespons
*/
public abstract class AbstractODataRetrieveRequest<V, T extends Format>
extends AbstractODataBasicRequest<ODataRetrieveResponse<V>, T>
- implements ODataRetrieveRequest<V, T>, ODataBatchableRequest {
+ implements ODataRetrieveRequest<V, T> {
/**
* Private constructor.
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/68f27d57/lib/client-core/src/test/java/org/apache/olingo/client/core/it/v3/BatchTestITCase.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/test/java/org/apache/olingo/client/core/it/v3/BatchTestITCase.java b/lib/client-core/src/test/java/org/apache/olingo/client/core/it/v3/BatchTestITCase.java
index 8ee3efd..4365600 100644
--- a/lib/client-core/src/test/java/org/apache/olingo/client/core/it/v3/BatchTestITCase.java
+++ b/lib/client-core/src/test/java/org/apache/olingo/client/core/it/v3/BatchTestITCase.java
@@ -18,389 +18,429 @@
*/
package org.apache.olingo.client.core.it.v3;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.Iterator;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import org.apache.http.HttpResponse;
+import org.apache.olingo.client.api.ODataBatchConstants;
+import org.apache.olingo.client.api.communication.request.ODataStreamManager;
+import org.apache.olingo.client.api.communication.request.batch.BatchStreamManager;
+import org.apache.olingo.client.api.communication.request.batch.ODataBatchRequest;
+import org.apache.olingo.client.api.communication.request.batch.ODataBatchResponseItem;
+import org.apache.olingo.client.api.communication.request.batch.ODataChangeset;
+import org.apache.olingo.client.api.communication.request.batch.ODataRetrieve;
+import org.apache.olingo.client.api.communication.request.cud.ODataEntityCreateRequest;
+import org.apache.olingo.client.api.communication.request.cud.ODataEntityUpdateRequest;
+import org.apache.olingo.client.api.communication.request.cud.v3.UpdateType;
+import org.apache.olingo.client.api.communication.request.retrieve.ODataEntityRequest;
+import org.apache.olingo.client.api.communication.response.ODataBatchResponse;
+import org.apache.olingo.client.api.communication.response.ODataEntityCreateResponse;
+import org.apache.olingo.client.api.communication.response.ODataEntityUpdateResponse;
+import org.apache.olingo.client.api.communication.response.ODataResponse;
+import org.apache.olingo.client.api.uri.v3.URIBuilder;
+import org.apache.olingo.client.core.communication.request.AbstractODataStreamManager;
+import org.apache.olingo.client.core.communication.request.Wrapper;
+import org.apache.olingo.client.core.communication.request.batch.ODataChangesetResponseItem;
+import org.apache.olingo.client.core.communication.request.batch.ODataRetrieveResponseItem;
+import org.apache.olingo.client.core.communication.request.retrieve.ODataEntityRequestImpl;
+import org.apache.olingo.client.core.communication.request.retrieve.ODataEntityRequestImpl.ODataEntityResponseImpl;
+import org.apache.olingo.client.core.uri.URIUtils;
+import org.apache.olingo.commons.api.domain.v3.ODataEntity;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
+import org.apache.olingo.commons.api.format.ODataPubFormat;
+import org.junit.Ignore;
+import org.junit.Test;
+
public class BatchTestITCase extends AbstractTestITCase {
-// private static String PREFIX = "!!PREFIX!!";
-//
-// private static String SUFFIX = "!!SUFFIX!!";
-//
-// private static int MAX = 10000;
-//
-// @Test
-// @Ignore
-// public void stringStreaming() {
-// final TestStreamManager streaming = new TestStreamManager();
-//
-// new StreamingThread(streaming).start();
-//
-// streaming.addObject((PREFIX + "\n").getBytes());
-//
-// for (int i = 0; i <= MAX; i++) {
-// streaming.addObject((i + ") send info\n").getBytes());
-// }
-//
-// streaming.addObject((SUFFIX).getBytes());
-// streaming.finalizeBody();
-// }
-//
-// @Test
-// @Ignore
-// public void emptyBatchRequest() {
-// // create your request
-// final ODataBatchRequest request = client.getBatchRequestFactory().getBatchRequest(testStaticServiceRootURL);
-//
-// final BatchStreamManager payload = request.execute();
-// final ODataBatchResponse response = payload.getResponse();
-//
-// assertEquals(202, response.getStatusCode());
-// assertEquals("Accepted", response.getStatusMessage());
-//
-// final Iterator<ODataBatchResponseItem> iter = response.getBody();
-// assertFalse(iter.hasNext());
-// }
-//
-// @Test
-// @Ignore
-// public void changesetWithError() {
-// // create your request
-// final ODataBatchRequest request = client.getBatchRequestFactory().getBatchRequest(testStaticServiceRootURL);
-//
-// final BatchStreamManager payload = request.execute();
-// final ODataChangeset changeset = payload.addChangeset();
-//
-// URIBuilder<?> targetURI;
-// ODataEntityCreateRequest createReq;
-//
-// targetURI = client.getURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("Customer");
-// for (int i = 1; i <= 2; i++) {
-// // Create Customer into the changeset
-// createReq = client.getCUDRequestFactory().getEntityCreateRequest(
-// targetURI.build(),
-// getSampleCustomerProfile(100 + i, "Sample customer", false));
-// createReq.setFormat(ODataPubFormat.JSON);
-// changeset.addRequest(createReq);
-// }
-//
-// targetURI = client.getURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("WrongEntitySet");
-// createReq = client.getCUDRequestFactory().getEntityCreateRequest(
-// targetURI.build(),
-// getSampleCustomerProfile(105, "Sample customer", false));
-// createReq.setFormat(ODataPubFormat.JSON);
-// changeset.addRequest(createReq);
-//
-// targetURI = client.getURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("Customer");
-// for (int i = 3; i <= 4; i++) {
-// // Create Customer into the changeset
-// createReq = client.getCUDRequestFactory().getEntityCreateRequest(
-// targetURI.build(),
-// getSampleCustomerProfile(100 + i, "Sample customer", false));
-// createReq.setFormat(ODataPubFormat.ATOM);
-// changeset.addRequest(createReq);
-// }
-//
-// final ODataBatchResponse response = payload.getResponse();
-// assertEquals(202, response.getStatusCode());
-// assertEquals("Accepted", response.getStatusMessage());
-//
-// final Iterator<ODataBatchResponseItem> iter = response.getBody();
-// final ODataChangesetResponseItem chgResponseItem = (ODataChangesetResponseItem) iter.next();
-//
-// final ODataResponse res = chgResponseItem.next();
-// assertEquals(404, res.getStatusCode());
-// assertEquals("Not Found", res.getStatusMessage());
-// assertEquals(Integer.valueOf(3), Integer.valueOf(
-// res.getHeader(ODataBatchConstants.CHANGESET_CONTENT_ID_NAME).iterator().next()));
-// assertFalse(chgResponseItem.hasNext());
-// }
-//
-// @Test
-// @Ignore
-// public void changesetWithReference() {
-// // create your request
-// final ODataBatchRequest request = client.getBatchRequestFactory().getBatchRequest(testStaticServiceRootURL);
-// final BatchStreamManager streamManager = request.execute();
-//
-// final ODataChangeset changeset = streamManager.addChangeset();
-// ODataEntity customer = getSampleCustomerProfile(20, "sample customer", false);
-//
-// URIBuilder<?> uriBuilder = client.getURIBuilder(testAuthServiceRootURL).appendEntitySetSegment("Customer");
-//
-// // add create request
-// final ODataEntityCreateRequest createReq =
-// client.getCUDRequestFactory().getEntityCreateRequest(uriBuilder.build(), customer);
-//
-// changeset.addRequest(createReq);
-//
-// // retrieve request reference
-// int createRequestRef = changeset.getLastContentId();
-//
-// // add update request: link CustomerInfo(17) to the new customer
-// final ODataEntity customerChanges = client.getObjectFactory().newEntity(customer.getName());
-// customerChanges.addLink(client.getObjectFactory().newEntityNavigationLink(
-// "Info",
-// client.getURIBuilder(testAuthServiceRootURL).appendEntitySetSegment("CustomerInfo").
-// appendKeySegment(17).build()));
-//
-// final ODataEntityUpdateRequest updateReq = client.getCUDRequestFactory().getEntityUpdateRequest(
-// URI.create("$" + createRequestRef), UpdateType.PATCH, customerChanges);
-//
-// changeset.addRequest(updateReq);
-//
-// final ODataBatchResponse response = streamManager.getResponse();
-// assertEquals(202, response.getStatusCode());
-// assertEquals("Accepted", response.getStatusMessage());
-//
-// // verify response payload ...
-// final Iterator<ODataBatchResponseItem> iter = response.getBody();
-//
-// final ODataBatchResponseItem item = iter.next();
-// assertTrue(item instanceof ODataChangesetResponseItem);
-//
-// final ODataChangesetResponseItem chgitem = (ODataChangesetResponseItem) item;
-//
-// ODataResponse res = chgitem.next();
-// assertEquals(201, res.getStatusCode());
-// assertTrue(res instanceof ODataEntityCreateResponse);
-//
-// customer = ((ODataEntityCreateResponse) res).getBody();
-//
-// ODataEntityRequest req = client.getRetrieveRequestFactory().getEntityRequest(
-// URIUtils.getURI(testStaticServiceRootURL, customer.getEditLink().toASCIIString() + "/Info"));
-//
-// assertEquals(Integer.valueOf(17),
-// req.execute().getBody().getProperty("CustomerInfoId").getPrimitiveValue().<Integer>toCastValue());
-//
-// res = chgitem.next();
-// assertEquals(204, res.getStatusCode());
-// assertTrue(res instanceof ODataEntityUpdateResponse);
-//
-// // clean ...
-// assertEquals(204, client.getCUDRequestFactory().getDeleteRequest(
-// URIUtils.getURI(testStaticServiceRootURL, customer.getEditLink().toASCIIString())).execute().
-// getStatusCode());
-//
-// try {
-// client.getRetrieveRequestFactory().getEntityRequest(
-// URIUtils.getURI(testStaticServiceRootURL, customer.getEditLink().toASCIIString())).
-// execute().getBody();
-// fail();
-// } catch (Exception e) {
-// // ignore
-// }
-// }
-//
-// @Test
-// @Ignore
-// public void batchRequest() {
-// // create your request
-// final ODataBatchRequest request = client.getBatchRequestFactory().getBatchRequest(testStaticServiceRootURL);
-//
-// final BatchStreamManager streamManager = request.execute();
-//
-// // -------------------------------------------
-// // Add retrieve item
-// // -------------------------------------------
-// ODataRetrieve retrieve = streamManager.addRetrieve();
-//
-// // prepare URI
-// URIBuilder<?> targetURI = client.getURIBuilder(testStaticServiceRootURL);
-// targetURI.appendEntitySetSegment("Customer").appendKeySegment(-10).
-// expand("Logins").select("CustomerId,Logins/Username");
-//
-// // create new request
-// ODataEntityRequest queryReq = client.getRetrieveRequestFactory().getEntityRequest(targetURI.build());
-// queryReq.setFormat(ODataPubFormat.ATOM);
-//
-// retrieve.setRequest(queryReq);
-// // -------------------------------------------
-//
-// // -------------------------------------------
-// // Add changeset item
-// // -------------------------------------------
-// final ODataChangeset changeset = streamManager.addChangeset();
-//
-// // Update Product into the changeset
-// targetURI = client.getURIBuilder(testStaticServiceRootURL).
-// appendEntitySetSegment("Product").appendKeySegment(-10);
-// final URI editLink = targetURI.build();
-//
-// final ODataEntity merge = client.getObjectFactory().newEntity(TEST_PRODUCT_TYPE);
-// merge.setEditLink(editLink);
-//
-// merge.getProperties().add(client.getObjectFactory().newPrimitiveProperty(
-// "Description", client.getPrimitiveValueBuilder().setText("new description from batch").build()));
-//
-// final ODataEntityUpdateRequest changeReq =
-// client.getCUDRequestFactory().getEntityUpdateRequest(UpdateType.MERGE, merge);
-// changeReq.setFormat(ODataPubFormat.JSON_FULL_METADATA);
-// changeReq.setIfMatch(getETag(editLink));
-//
-// changeset.addRequest(changeReq);
-//
-// // Create Customer into the changeset
-// targetURI = client.getURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("Customer");
-// final ODataEntity original = getSampleCustomerProfile(1000, "Sample customer", false);
-// final ODataEntityCreateRequest createReq =
-// client.getCUDRequestFactory().getEntityCreateRequest(targetURI.build(), original);
-// createReq.setFormat(ODataPubFormat.ATOM);
-// changeset.addRequest(createReq);
-// // -------------------------------------------
-//
-// // -------------------------------------------
-// // Add retrieve item
-// // -------------------------------------------
-// retrieve = streamManager.addRetrieve();
-//
-// // prepare URI
-// targetURI = client.getURIBuilder(testStaticServiceRootURL).
-// appendEntitySetSegment("Product").appendKeySegment(-10);
-//
-// // create new request
-// queryReq = client.getRetrieveRequestFactory().getEntityRequest(targetURI.build());
-//
-// retrieve.setRequest(queryReq);
-// // -------------------------------------------
-//
-// final ODataBatchResponse response = streamManager.getResponse();
-// assertEquals(202, response.getStatusCode());
-// assertEquals("Accepted", response.getStatusMessage());
-//
-// final Iterator<ODataBatchResponseItem> iter = response.getBody();
-//
-// // retrive the first item (ODataRetrieve)
-// ODataBatchResponseItem item = iter.next();
-// assertTrue(item instanceof ODataRetrieveResponseItem);
-//
-// ODataRetrieveResponseItem retitem = (ODataRetrieveResponseItem) item;
-// ODataResponse res = retitem.next();
-// assertTrue(res instanceof ODataEntityResponseImpl);
-// assertEquals(200, res.getStatusCode());
-// assertEquals("OK", res.getStatusMessage());
-//
-// ODataEntityResponseImpl entres = (ODataEntityResponseImpl) res;
-// ODataEntity entity = entres.getBody();
-// assertEquals(new Integer(-10), entity.getProperty("CustomerId").getPrimitiveValue().<Integer>toCastValue());
-//
-// // retrieve the second item (ODataChangeset)
-// item = iter.next();
-// assertTrue(item instanceof ODataChangesetResponseItem);
-//
-// final ODataChangesetResponseItem chgitem = (ODataChangesetResponseItem) item;
-// res = chgitem.next();
-// assertTrue(res instanceof ODataEntityUpdateResponse);
-// assertEquals(204, res.getStatusCode());
-// assertEquals("No Content", res.getStatusMessage());
-//
-// res = chgitem.next();
-// assertTrue(res instanceof ODataEntityCreateResponse);
-// assertEquals(201, res.getStatusCode());
-// assertEquals("Created", res.getStatusMessage());
-//
-// final ODataEntityCreateResponse createres = (ODataEntityCreateResponse) res;
-// entity = createres.getBody();
-// assertEquals(new Integer(1000), entity.getProperty("CustomerId").getPrimitiveValue().<Integer>toCastValue());
-//
-// // retrive the third item (ODataRetrieve)
-// item = iter.next();
-// assertTrue(item instanceof ODataRetrieveResponseItem);
-//
-// retitem = (ODataRetrieveResponseItem) item;
-// res = retitem.next();
-// assertTrue(res instanceof ODataEntityResponseImpl);
-// assertEquals(200, res.getStatusCode());
-// assertEquals("OK", res.getStatusMessage());
-//
-// entres = (ODataEntityResponseImpl) res;
-// entity = entres.getBody();
-// assertEquals("new description from batch",
-// entity.getProperty("Description").getPrimitiveValue().<String>toCastValue());
-//
-// assertFalse(iter.hasNext());
-// }
-//
-// private static class TestStreamManager extends AbstractODataStreamManager<ODataBatchResponse> {
-//
-// public TestStreamManager() {
-// super(new Wrapper<Future<HttpResponse>>());
-// }
-//
-// public ODataStreamManager<ODataBatchResponse> addObject(byte[] src) {
-// stream(src);
-// return this;
-// }
-//
-// @Override
-// protected ODataBatchResponse getResponse(long timeout, TimeUnit unit) {
-// throw new UnsupportedOperationException("Not supported yet.");
-// }
-// };
-//
-// /**
-// * To be used for debug purposes.
-// */
-// private static class StreamingThread extends Thread {
-//
-// private final TestStreamManager streaming;
-//
-// public StreamingThread(final TestStreamManager streaming) {
-// this.streaming = streaming;
-// }
-//
-// @Override
-// public void run() {
-// try {
-// final StringBuilder builder = new StringBuilder();
-//
-// byte[] buff = new byte[1024];
-//
-// int len;
-//
-// while ((len = streaming.getBody().read(buff)) >= 0) {
-// builder.append(new String(buff, 0, len));
-// }
-//
-// assertTrue(builder.toString().startsWith(PREFIX));
-// assertTrue(builder.toString().contains((MAX / 2) + ") send info"));
-// assertTrue(builder.toString().contains((MAX / 3) + ") send info"));
-// assertTrue(builder.toString().contains((MAX / 20) + ") send info"));
-// assertTrue(builder.toString().contains((MAX / 30) + ") send info"));
-// assertTrue(builder.toString().contains(MAX + ") send info"));
-// assertTrue(builder.toString().endsWith(SUFFIX));
-//
-// } catch (IOException e) {
-// fail();
-// }
-// }
-// }
-//
-// private static class BatchStreamingThread extends Thread {
-//
-// private final BatchStreamManager streaming;
-//
-// public BatchStreamingThread(final BatchStreamManager streaming) {
-// this.streaming = streaming;
-// }
-//
-// @Override
-// public void run() {
-// try {
-// final StringBuilder builder = new StringBuilder();
-//
-// byte[] buff = new byte[1024];
-//
-// int len;
-//
-// while ((len = streaming.getBody().read(buff)) >= 0) {
-// builder.append(new String(buff, 0, len));
-// }
-//
-// LOG.debug("Batch request {}", builder.toString());
-//
-// assertTrue(builder.toString().contains("Content-Id:2"));
-// assertTrue(builder.toString().contains("GET " + servicesODataServiceRootURL));
-// } catch (IOException e) {
-// fail();
-// }
-// }
-// }
+ private static String PREFIX = "!!PREFIX!!";
+
+ private static String SUFFIX = "!!SUFFIX!!";
+
+ private static int MAX = 10000;
+
+ @Test
+ public void stringStreaming() {
+ final TestStreamManager streaming = new TestStreamManager();
+
+ new StreamingThread(streaming).start();
+
+ streaming.addObject((PREFIX + "\n").getBytes());
+
+ for (int i = 0; i <= MAX; i++) {
+ streaming.addObject((i + ") send info\n").getBytes());
+ }
+
+ streaming.addObject((SUFFIX).getBytes());
+ streaming.finalizeBody();
+ }
+
+ @Test
+ public void emptyBatchRequest() {
+ // create your request
+ final ODataBatchRequest request = client.getBatchRequestFactory().getBatchRequest(testStaticServiceRootURL);
+
+ final BatchStreamManager payload = request.execute();
+ final ODataBatchResponse response = payload.getResponse();
+
+ assertEquals(202, response.getStatusCode());
+ assertEquals("Accepted", response.getStatusMessage());
+
+ final Iterator<ODataBatchResponseItem> iter = response.getBody();
+ assertFalse(iter.hasNext());
+ }
+
+ @Test
+ public void changesetWithError() {
+ // create your request
+ final ODataBatchRequest request = client.getBatchRequestFactory().getBatchRequest(testStaticServiceRootURL);
+
+ final BatchStreamManager payload = request.execute();
+ final ODataChangeset changeset = payload.addChangeset();
+
+ URIBuilder targetURI;
+ ODataEntityCreateRequest<ODataEntity> createReq;
+
+ targetURI = client.getURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("Customer");
+ for (int i = 1; i <= 2; i++) {
+ // Create Customer into the changeset
+ createReq = client.getCUDRequestFactory().getEntityCreateRequest(
+ targetURI.build(),
+ getSampleCustomerProfile(100 + i, "Sample customer", false));
+ createReq.setFormat(ODataPubFormat.JSON);
+ changeset.addRequest(createReq);
+ }
+
+ targetURI = client.getURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("WrongEntitySet");
+ createReq = client.getCUDRequestFactory().getEntityCreateRequest(
+ targetURI.build(),
+ getSampleCustomerProfile(105, "Sample customer", false));
+ createReq.setFormat(ODataPubFormat.JSON);
+ changeset.addRequest(createReq);
+
+ targetURI = client.getURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("Customer");
+ for (int i = 3; i <= 4; i++) {
+ // Create Customer into the changeset
+ createReq = client.getCUDRequestFactory().getEntityCreateRequest(
+ targetURI.build(),
+ getSampleCustomerProfile(100 + i, "Sample customer", false));
+ createReq.setFormat(ODataPubFormat.ATOM);
+ changeset.addRequest(createReq);
+ }
+
+ final ODataBatchResponse response = payload.getResponse();
+ assertEquals(202, response.getStatusCode());
+ assertEquals("Accepted", response.getStatusMessage());
+
+ final Iterator<ODataBatchResponseItem> iter = response.getBody();
+ final ODataChangesetResponseItem chgResponseItem = (ODataChangesetResponseItem) iter.next();
+
+ final ODataResponse res = chgResponseItem.next();
+ assertEquals(404, res.getStatusCode());
+ assertEquals("Not Found", res.getStatusMessage());
+ assertEquals(Integer.valueOf(3), Integer.valueOf(
+ res.getHeader(ODataBatchConstants.CHANGESET_CONTENT_ID_NAME).iterator().next()));
+ assertFalse(chgResponseItem.hasNext());
+ }
+
+ @Test
+ @Ignore
+ @SuppressWarnings("unchecked")
+ public void changesetWithReference() throws EdmPrimitiveTypeException {
+ // create your request
+ final ODataBatchRequest request = client.getBatchRequestFactory().getBatchRequest(testStaticServiceRootURL);
+ final BatchStreamManager streamManager = request.execute();
+
+ final ODataChangeset changeset = streamManager.addChangeset();
+ ODataEntity customer = getSampleCustomerProfile(20, "sample customer", false);
+
+ URIBuilder uriBuilder = client.getURIBuilder(testAuthServiceRootURL).appendEntitySetSegment("Customer");
+
+ // add create request
+ final ODataEntityCreateRequest<ODataEntity> createReq =
+ client.getCUDRequestFactory().getEntityCreateRequest(uriBuilder.build(), customer);
+
+ changeset.addRequest(createReq);
+
+ // retrieve request reference
+ int createRequestRef = changeset.getLastContentId();
+
+ // add update request: link CustomerInfo(17) to the new customer
+ final ODataEntity customerChanges = client.getObjectFactory().newEntity(customer.getTypeName());
+ customerChanges.addLink(client.getObjectFactory().newEntityNavigationLink(
+ "Info",
+ client.getURIBuilder(testAuthServiceRootURL).appendEntitySetSegment("CustomerInfo").
+ appendKeySegment(17).build()));
+
+ final ODataEntityUpdateRequest updateReq = client.getCUDRequestFactory().getEntityUpdateRequest(
+ URI.create("$" + createRequestRef), UpdateType.PATCH, customerChanges);
+
+ changeset.addRequest(updateReq);
+
+ final ODataBatchResponse response = streamManager.getResponse();
+ assertEquals(202, response.getStatusCode());
+ assertEquals("Accepted", response.getStatusMessage());
+
+ // verify response payload ...
+ final Iterator<ODataBatchResponseItem> iter = response.getBody();
+
+ final ODataBatchResponseItem item = iter.next();
+ assertTrue(item instanceof ODataChangesetResponseItem);
+
+ final ODataChangesetResponseItem chgitem = (ODataChangesetResponseItem) item;
+
+ ODataResponse res = chgitem.next();
+ assertEquals(201, res.getStatusCode());
+ assertTrue(res instanceof ODataEntityCreateResponse);
+
+ customer = ((ODataEntityCreateResponse<ODataEntity>) res).getBody();
+
+ ODataEntityRequest<ODataEntity> req = client.getRetrieveRequestFactory().getEntityRequest(
+ URIUtils.getURI(testStaticServiceRootURL, customer.getEditLink().toASCIIString() + "/Info"));
+
+ assertEquals(Integer.valueOf(17),
+ req.execute().getBody().getProperty("CustomerInfoId").getPrimitiveValue().toCastValue(Integer.class));
+
+ res = chgitem.next();
+ assertEquals(204, res.getStatusCode());
+ assertTrue(res instanceof ODataEntityUpdateResponse);
+
+ // clean ...
+ assertEquals(204, client.getCUDRequestFactory().getDeleteRequest(
+ URIUtils.getURI(testStaticServiceRootURL, customer.getEditLink().toASCIIString())).execute().
+ getStatusCode());
+
+ try {
+ client.getRetrieveRequestFactory().getEntityRequest(
+ URIUtils.getURI(testStaticServiceRootURL, customer.getEditLink().toASCIIString())).
+ execute().getBody();
+ fail();
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void batchRequest() throws EdmPrimitiveTypeException {
+ // create your request
+ final ODataBatchRequest request = client.getBatchRequestFactory().getBatchRequest(testStaticServiceRootURL);
+
+ final BatchStreamManager streamManager = request.execute();
+
+ // -------------------------------------------
+ // Add retrieve item
+ // -------------------------------------------
+ ODataRetrieve retrieve = streamManager.addRetrieve();
+
+ // prepare URI
+ URIBuilder targetURI = client.getURIBuilder(testStaticServiceRootURL);
+ targetURI.appendEntitySetSegment("Customer").appendKeySegment(-10).
+ expand("Logins").select("CustomerId,Logins/Username");
+
+ // create new request
+ ODataEntityRequest<ODataEntity> queryReq = client.getRetrieveRequestFactory().getEntityRequest(targetURI.build());
+ queryReq.setFormat(ODataPubFormat.ATOM);
+
+ retrieve.setRequest(queryReq);
+ // -------------------------------------------
+
+ // -------------------------------------------
+ // Add changeset item
+ // -------------------------------------------
+ final ODataChangeset changeset = streamManager.addChangeset();
+
+ // Update Product into the changeset
+ targetURI = client.getURIBuilder(testStaticServiceRootURL).
+ appendEntitySetSegment("Product").appendKeySegment(-10);
+ final URI editLink = targetURI.build();
+
+ final ODataEntity merge = client.getObjectFactory().newEntity(TEST_PRODUCT_TYPE);
+ merge.setEditLink(editLink);
+
+ merge.getProperties().add(client.getObjectFactory().newPrimitiveProperty(
+ "Description",
+ client.getObjectFactory().newPrimitiveValueBuilder().buildString("new description from batch")));
+
+ final ODataEntityUpdateRequest changeReq =
+ client.getCUDRequestFactory().getEntityUpdateRequest(UpdateType.MERGE, merge);
+ changeReq.setFormat(ODataPubFormat.JSON_FULL_METADATA);
+ changeReq.setIfMatch(getETag(editLink));
+
+ changeset.addRequest(changeReq);
+
+ // Create Customer into the changeset
+ targetURI = client.getURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("Customer");
+ final ODataEntity original = getSampleCustomerProfile(1000, "Sample customer", false);
+ final ODataEntityCreateRequest<ODataEntity> createReq =
+ client.getCUDRequestFactory().getEntityCreateRequest(targetURI.build(), original);
+ createReq.setFormat(ODataPubFormat.ATOM);
+ changeset.addRequest(createReq);
+ // -------------------------------------------
+
+ // -------------------------------------------
+ // Add retrieve item
+ // -------------------------------------------
+ retrieve = streamManager.addRetrieve();
+
+ // prepare URI
+ targetURI = client.getURIBuilder(testStaticServiceRootURL).
+ appendEntitySetSegment("Product").appendKeySegment(-10);
+
+ // create new request
+ queryReq = client.getRetrieveRequestFactory().getEntityRequest(targetURI.build());
+
+ retrieve.setRequest(queryReq);
+ // -------------------------------------------
+
+ final ODataBatchResponse response = streamManager.getResponse();
+ assertEquals(202, response.getStatusCode());
+ assertEquals("Accepted", response.getStatusMessage());
+ final Iterator<ODataBatchResponseItem> iter = response.getBody();
+
+ // retrive the first item (ODataRetrieve)
+ ODataBatchResponseItem item = iter.next();
+ assertTrue(item instanceof ODataRetrieveResponseItem);
+
+ ODataRetrieveResponseItem retitem = (ODataRetrieveResponseItem) item;
+ ODataResponse res = retitem.next();
+ assertTrue(res instanceof ODataEntityResponseImpl);
+ assertEquals(200, res.getStatusCode());
+ assertEquals("OK", res.getStatusMessage());
+
+ ODataEntityRequestImpl<ODataEntity>.ODataEntityResponseImpl entres =
+ (ODataEntityRequestImpl<ODataEntity>.ODataEntityResponseImpl) res;
+
+ ODataEntity entity = entres.getBody();
+ assertEquals(new Integer(-10), entity.getProperty("CustomerId").getPrimitiveValue().toCastValue(Integer.class));
+
+ // retrieve the second item (ODataChangeset)
+ item = iter.next();
+ assertTrue(item instanceof ODataChangesetResponseItem);
+
+ final ODataChangesetResponseItem chgitem = (ODataChangesetResponseItem) item;
+ res = chgitem.next();
+ assertTrue(res instanceof ODataEntityUpdateResponse);
+ assertEquals(204, res.getStatusCode());
+ assertEquals("No Content", res.getStatusMessage());
+
+ res = chgitem.next();
+ assertTrue(res instanceof ODataEntityCreateResponse);
+ assertEquals(201, res.getStatusCode());
+ assertEquals("Created", res.getStatusMessage());
+
+ final ODataEntityCreateResponse<ODataEntity> createres = (ODataEntityCreateResponse<ODataEntity>) res;
+ entity = createres.getBody();
+ assertEquals(new Integer(1000), entity.getProperty("CustomerId").getPrimitiveValue().toCastValue(Integer.class));
+
+ // retrive the third item (ODataRetrieve)
+ item = iter.next();
+ assertTrue(item instanceof ODataRetrieveResponseItem);
+
+ retitem = (ODataRetrieveResponseItem) item;
+ res = retitem.next();
+ assertTrue(res instanceof ODataEntityResponseImpl);
+ assertEquals(200, res.getStatusCode());
+ assertEquals("OK", res.getStatusMessage());
+
+ entres = (ODataEntityRequestImpl<ODataEntity>.ODataEntityResponseImpl) res;
+ entity = entres.getBody();
+ assertEquals("new description from batch",
+ entity.getProperty("Description").getPrimitiveValue().toCastValue(String.class));
+
+ assertFalse(iter.hasNext());
+ }
+
+ private static class TestStreamManager extends AbstractODataStreamManager<ODataBatchResponse> {
+
+ public TestStreamManager() {
+ super(new Wrapper<Future<HttpResponse>>());
+ }
+
+ public ODataStreamManager<ODataBatchResponse> addObject(byte[] src) {
+ stream(src);
+ return this;
+ }
+
+ @Override
+ protected ODataBatchResponse getResponse(long timeout, TimeUnit unit) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+ };
+
+ /**
+ * To be used for debug purposes.
+ */
+ private static class StreamingThread extends Thread {
+
+ private final TestStreamManager streaming;
+
+ public StreamingThread(final TestStreamManager streaming) {
+ this.streaming = streaming;
+ }
+
+ @Override
+ public void run() {
+ try {
+ final StringBuilder builder = new StringBuilder();
+
+ byte[] buff = new byte[1024];
+
+ int len;
+
+ while ((len = streaming.getBody().read(buff)) >= 0) {
+ builder.append(new String(buff, 0, len));
+ }
+
+ assertTrue(builder.toString().startsWith(PREFIX));
+ assertTrue(builder.toString().contains((MAX / 2) + ") send info"));
+ assertTrue(builder.toString().contains((MAX / 3) + ") send info"));
+ assertTrue(builder.toString().contains((MAX / 20) + ") send info"));
+ assertTrue(builder.toString().contains((MAX / 30) + ") send info"));
+ assertTrue(builder.toString().contains(MAX + ") send info"));
+ assertTrue(builder.toString().endsWith(SUFFIX));
+
+ } catch (IOException e) {
+ fail();
+ }
+ }
+ }
+
+ private static class BatchStreamingThread extends Thread {
+
+ private final BatchStreamManager streaming;
+
+ public BatchStreamingThread(final BatchStreamManager streaming) {
+ this.streaming = streaming;
+ }
+
+ @Override
+ public void run() {
+ try {
+ final StringBuilder builder = new StringBuilder();
+
+ byte[] buff = new byte[1024];
+
+ int len;
+
+ while ((len = streaming.getBody().read(buff)) >= 0) {
+ builder.append(new String(buff, 0, len));
+ }
+
+ LOG.debug("Batch request {}", builder.toString());
+
+ assertTrue(builder.toString().contains("Content-Id:2"));
+ assertTrue(builder.toString().contains("GET " + testStaticServiceRootURL));
+ } catch (IOException e) {
+ fail();
+ }
+ }
+ }
}