Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add full support for "batch" operation on tables

  • Loading branch information...
commit 802e9b0f69ac0b7e35a0daf143dd2b934f0e4d34 1 parent 3f5f5d7
Renaud Paquay authored lodejard committed
View
18 ...oft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/utils/pipeline/PipelineHelpers.java
@@ -2,15 +2,15 @@
* Copyright 2011 Microsoft Corporation
*
* Licensed 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
+ * 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.
+ * 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.microsoft.windowsazure.services.core.utils.pipeline;
@@ -28,7 +28,7 @@
public class PipelineHelpers {
public static void ThrowIfError(ClientResponse r) {
- if (r.getStatus() >= 300) {
+ if (r.getStatus() >= 400) {
throw new UniformInterfaceException(r);
}
}
View
2  microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/Exports.java
@@ -18,6 +18,7 @@
import com.microsoft.windowsazure.services.table.implementation.AtomReaderWriter;
import com.microsoft.windowsazure.services.table.implementation.DefaultEdmValueConterter;
import com.microsoft.windowsazure.services.table.implementation.DefaultXMLStreamFactory;
+import com.microsoft.windowsazure.services.table.implementation.HttpReaderWriter;
import com.microsoft.windowsazure.services.table.implementation.MimeReaderWriter;
import com.microsoft.windowsazure.services.table.implementation.SharedKeyFilter;
import com.microsoft.windowsazure.services.table.implementation.SharedKeyLiteFilter;
@@ -36,6 +37,7 @@ public void register(Builder.Registry registry) {
registry.add(XMLStreamFactory.class, DefaultXMLStreamFactory.class);
registry.add(AtomReaderWriter.class);
registry.add(MimeReaderWriter.class);
+ registry.add(HttpReaderWriter.class);
registry.add(EdmValueConverter.class, DefaultEdmValueConterter.class);
}
}
View
168 ...t-azure-api/src/main/java/com/microsoft/windowsazure/services/table/implementation/HttpReaderWriter.java
@@ -0,0 +1,168 @@
+package com.microsoft.windowsazure.services.table.implementation;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.util.Enumeration;
+
+import javax.activation.DataSource;
+import javax.inject.Inject;
+import javax.mail.Header;
+import javax.mail.MessagingException;
+import javax.mail.internet.InternetHeaders;
+
+import com.sun.mail.util.LineInputStream;
+
+public class HttpReaderWriter {
+
+ @Inject
+ public HttpReaderWriter() {
+ }
+
+ public StatusLine parseStatusLine(DataSource ds) {
+ try {
+ LineInputStream stream = new LineInputStream(ds.getInputStream());
+ String line = stream.readLine();
+ StringReader lineReader = new StringReader(line);
+
+ expect(lineReader, "HTTP/1.1");
+ expect(lineReader, " ");
+ String statusString = extractInput(lineReader, ' ');
+ String reason = extractInput(lineReader, -1);
+
+ return new StatusLine().setStatus(Integer.parseInt(statusString)).setReason(reason);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public InternetHeaders parseHeaders(DataSource ds) {
+ try {
+ return new InternetHeaders(ds.getInputStream());
+ }
+ catch (MessagingException e) {
+ throw new RuntimeException(e);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public InputStream parseEntity(DataSource ds) {
+ try {
+ return ds.getInputStream();
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void appendMethod(OutputStream stream, String verb, URI uri) {
+ try {
+ String method = String.format("%s %s %s\r\n", verb, uri, "HTTP/1.1");
+ stream.write(method.getBytes("UTF-8"));
+ }
+ catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void appendHeaders(OutputStream stream, InternetHeaders headers) {
+ try {
+ // Headers
+ Enumeration<Header> e = headers.getAllHeaders();
+ while (e.hasMoreElements()) {
+ Header header = e.nextElement();
+
+ String headerLine = String.format("%s: %s\r\n", header.getName(), header.getValue());
+ stream.write(headerLine.getBytes("UTF-8"));
+ }
+
+ // Empty line
+ stream.write("\r\n".getBytes("UTF-8"));
+ }
+ catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void appendEntity(OutputStream stream, InputStream entity) {
+ try {
+ byte[] buffer = new byte[1024];
+ while (true) {
+ int n = entity.read(buffer);
+ if (n == -1)
+ break;
+ stream.write(buffer, 0, n);
+ }
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private void expect(Reader reader, String string) {
+ try {
+ for (int i = 0; i < string.length(); i++) {
+ int ch = reader.read();
+ if (ch < 0)
+ throw new RuntimeException(String.format("Expected '%s', found '%s' instead", string,
+ string.substring(0, i) + ch));
+ }
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private String extractInput(Reader reader, int delimiter) {
+ try {
+ StringBuilder sb = new StringBuilder();
+ while (true) {
+ int ch = reader.read();
+ if (ch == -1 || ch == delimiter)
+ break;
+
+ sb.append((char) ch);
+ }
+ return sb.toString();
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public class StatusLine {
+ private int status;
+ private String reason;
+
+ public int getStatus() {
+ return status;
+ }
+
+ public StatusLine setStatus(int status) {
+ this.status = status;
+ return this;
+ }
+
+ public String getReason() {
+ return reason;
+ }
+
+ public StatusLine setReason(String reason) {
+ this.reason = reason;
+ return this;
+ }
+ }
+}
View
38 ...re-api/src/main/java/com/microsoft/windowsazure/services/table/implementation/InputStreamDataSource.java
@@ -0,0 +1,38 @@
+package com.microsoft.windowsazure.services.table.implementation;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import javax.activation.DataSource;
+
+public class InputStreamDataSource implements DataSource {
+ private final InputStream stream;
+ private final String contentType;
+
+ public InputStreamDataSource(InputStream stream, String contentType) {
+ this.stream = stream;
+ this.contentType = contentType;
+
+ }
+
+ @Override
+ public String getContentType() {
+ return contentType;
+ }
+
+ @Override
+ public InputStream getInputStream() throws IOException {
+ return stream;
+ }
+
+ @Override
+ public String getName() {
+ return null;
+ }
+
+ @Override
+ public OutputStream getOutputStream() throws IOException {
+ return null;
+ }
+}
View
50 ...t-azure-api/src/main/java/com/microsoft/windowsazure/services/table/implementation/MimeReaderWriter.java
@@ -3,15 +3,19 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
+import javax.activation.DataHandler;
+import javax.activation.DataSource;
import javax.inject.Inject;
import javax.mail.BodyPart;
import javax.mail.MessagingException;
import javax.mail.MultipartDataSource;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMultipart;
+import javax.mail.internet.MimePartDataSource;
public class MimeReaderWriter {
@@ -19,16 +23,20 @@
public MimeReaderWriter() {
}
- public MimeMultipart getMimeMultipart(List<String> bodyPartContents) {
+ public MimeMultipart getMimeMultipart(List<DataSource> bodyPartContents) {
try {
return getMimeMultipartCore(bodyPartContents);
}
catch (MessagingException e) {
throw new RuntimeException(e);
}
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
}
- private MimeMultipart getMimeMultipartCore(List<String> bodyPartContents) throws MessagingException {
+ private MimeMultipart getMimeMultipartCore(List<DataSource> bodyPartContents) throws MessagingException,
+ IOException {
// Create unique part boundary strings
String batchId = String.format("batch_%s", UUID.randomUUID().toString());
String changeSet = String.format("changeset_%s", UUID.randomUUID().toString());
@@ -38,14 +46,11 @@ private MimeMultipart getMimeMultipartCore(List<String> bodyPartContents) throws
//
MimeMultipart changeSets = new MimeMultipart(new SetBoundaryMultipartDataSource(changeSet));
- for (String bodyPart : bodyPartContents) {
+ for (DataSource bodyPart : bodyPartContents) {
MimeBodyPart mimeBodyPart = new MimeBodyPart();
- mimeBodyPart.setContent(bodyPart, "application/http");
-
- //Note: Both content type and encoding need to be set *after* setting content, because
- // MimeBodyPart implementation replaces them when calling "setContent".
- mimeBodyPart.setHeader("Content-Type", "application/http");
+ mimeBodyPart.setDataHandler(new DataHandler(bodyPart));
+ mimeBodyPart.setHeader("Content-Type", bodyPart.getContentType());
mimeBodyPart.setHeader("Content-Transfer-Encoding", "binary");
changeSets.addBodyPart(mimeBodyPart);
@@ -110,4 +115,33 @@ public BodyPart getBodyPart(int index) throws MessagingException {
return null;
}
}
+
+ public List<DataSource> parseParts(final InputStream entityInputStream, final String contentType) {
+ try {
+ return parsePartsCore(entityInputStream, contentType);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ catch (MessagingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private List<DataSource> parsePartsCore(InputStream entityInputStream, String contentType)
+ throws MessagingException, IOException {
+ DataSource ds = new InputStreamDataSource(entityInputStream, contentType);
+ MimeMultipart batch = new MimeMultipart(ds);
+ MimeBodyPart batchBody = (MimeBodyPart) batch.getBodyPart(0);
+
+ MimeMultipart changeSets = new MimeMultipart(new MimePartDataSource(batchBody));
+
+ List<DataSource> result = new ArrayList<DataSource>();
+ for (int i = 0; i < changeSets.getCount(); i++) {
+ BodyPart part = changeSets.getBodyPart(i);
+
+ result.add(new InputStreamDataSource(part.getInputStream(), part.getContentType()));
+ }
+ return result;
+ }
}
View
164 ...oft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/implementation/TableRestProxy.java
@@ -14,16 +14,20 @@
*/
package com.microsoft.windowsazure.services.table.implementation;
+import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Enumeration;
import java.util.List;
+import javax.activation.DataSource;
import javax.inject.Inject;
import javax.inject.Named;
+import javax.mail.Header;
+import javax.mail.internet.InternetHeaders;
import javax.mail.internet.MimeMultipart;
import com.microsoft.windowsazure.services.blob.implementation.ISO8601DateConverter;
@@ -32,15 +36,27 @@
import com.microsoft.windowsazure.services.core.ServiceFilter;
import com.microsoft.windowsazure.services.core.utils.CommaStringBuilder;
import com.microsoft.windowsazure.services.core.utils.DateFactory;
+import com.microsoft.windowsazure.services.core.utils.ServiceExceptionFactory;
import com.microsoft.windowsazure.services.core.utils.pipeline.ClientFilterAdapter;
import com.microsoft.windowsazure.services.core.utils.pipeline.HttpURLConnectionClient;
import com.microsoft.windowsazure.services.core.utils.pipeline.PipelineHelpers;
import com.microsoft.windowsazure.services.table.TableConfiguration;
import com.microsoft.windowsazure.services.table.TableContract;
+import com.microsoft.windowsazure.services.table.implementation.HttpReaderWriter.StatusLine;
import com.microsoft.windowsazure.services.table.models.BatchOperations;
-import com.microsoft.windowsazure.services.table.models.BatchOperations.InsertOperation;
+import com.microsoft.windowsazure.services.table.models.BatchOperations.DeleteEntityOperation;
+import com.microsoft.windowsazure.services.table.models.BatchOperations.InsertEntityOperation;
+import com.microsoft.windowsazure.services.table.models.BatchOperations.InsertOrMergeEntityOperation;
+import com.microsoft.windowsazure.services.table.models.BatchOperations.InsertOrReplaceEntityOperation;
+import com.microsoft.windowsazure.services.table.models.BatchOperations.MergeEntityOperation;
import com.microsoft.windowsazure.services.table.models.BatchOperations.Operation;
+import com.microsoft.windowsazure.services.table.models.BatchOperations.UpdateEntityOperation;
import com.microsoft.windowsazure.services.table.models.BatchResult;
+import com.microsoft.windowsazure.services.table.models.BatchResult.DeleteEntity;
+import com.microsoft.windowsazure.services.table.models.BatchResult.Entry;
+import com.microsoft.windowsazure.services.table.models.BatchResult.Error;
+import com.microsoft.windowsazure.services.table.models.BatchResult.InsertEntity;
+import com.microsoft.windowsazure.services.table.models.BatchResult.UpdateEntity;
import com.microsoft.windowsazure.services.table.models.BinaryFilter;
import com.microsoft.windowsazure.services.table.models.ConstantFilter;
import com.microsoft.windowsazure.services.table.models.DeleteEntityOptions;
@@ -63,8 +79,10 @@
import com.microsoft.windowsazure.services.table.models.UnaryFilter;
import com.microsoft.windowsazure.services.table.models.UpdateEntityResult;
import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.UniformInterfaceException;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.WebResource.Builder;
+import com.sun.jersey.core.header.InBoundHeaders;
public class TableRestProxy implements TableContract {
private static final String API_VERSION = "2011-08-18";
@@ -77,11 +95,12 @@
private final SharedKeyFilter filter;
private final AtomReaderWriter atomReaderWriter;
private final MimeReaderWriter mimeReaderWriter;
+ private final HttpReaderWriter httpReaderWriter;
@Inject
public TableRestProxy(HttpURLConnectionClient channel, @Named(TableConfiguration.URI) String url,
SharedKeyFilter filter, DateFactory dateFactory, ISO8601DateConverter iso8601DateConverter,
- AtomReaderWriter atomReaderWriter, MimeReaderWriter mimeReaderWriter) {
+ AtomReaderWriter atomReaderWriter, MimeReaderWriter mimeReaderWriter, HttpReaderWriter httpReaderWriter) {
this.channel = channel;
this.url = url;
@@ -92,12 +111,14 @@ public TableRestProxy(HttpURLConnectionClient channel, @Named(TableConfiguration
this.dateFactory = dateFactory;
this.atomReaderWriter = atomReaderWriter;
this.mimeReaderWriter = mimeReaderWriter;
+ this.httpReaderWriter = httpReaderWriter;
channel.addFilter(filter);
}
public TableRestProxy(HttpURLConnectionClient channel, ServiceFilter[] filters, String url, SharedKeyFilter filter,
DateFactory dateFactory, AtomReaderWriter atomReaderWriter, MimeReaderWriter mimeReaderWriter,
- RFC1123DateConverter dateMapper, ISO8601DateConverter iso8601DateConverter) {
+ HttpReaderWriter httpReaderWriter, RFC1123DateConverter dateMapper,
+ ISO8601DateConverter iso8601DateConverter) {
this.channel = channel;
this.filters = filters;
@@ -106,6 +127,7 @@ public TableRestProxy(HttpURLConnectionClient channel, ServiceFilter[] filters,
this.dateFactory = dateFactory;
this.atomReaderWriter = atomReaderWriter;
this.mimeReaderWriter = mimeReaderWriter;
+ this.httpReaderWriter = httpReaderWriter;
this.dateMapper = dateMapper;
this.iso8601DateConverter = iso8601DateConverter;
}
@@ -115,7 +137,8 @@ public TableContract withFilter(ServiceFilter filter) {
ServiceFilter[] newFilters = Arrays.copyOf(filters, filters.length + 1);
newFilters[filters.length] = filter;
return new TableRestProxy(this.channel, newFilters, this.url, this.filter, this.dateFactory,
- this.atomReaderWriter, this.mimeReaderWriter, this.dateMapper, this.iso8601DateConverter);
+ this.atomReaderWriter, this.mimeReaderWriter, this.httpReaderWriter, this.dateMapper,
+ this.iso8601DateConverter);
}
private void ThrowIfError(ClientResponse r) {
@@ -539,46 +562,111 @@ public BatchResult batch(BatchOperations operations, TableServiceOptions options
ClientResponse response = builder.post(ClientResponse.class, entity);
ThrowIfError(response);
- return null;
+ BatchResult result = new BatchResult();
+ result.setEntries(parseMimeMultipart(response, operations));
+
+ return result;
}
- private MimeMultipart createMimeMultipart(BatchOperations operations) {
- try {
- List<String> bodyPartContents = new ArrayList<String>();
- int contentId = 1;
- for (Operation operation : operations.getOperations()) {
-
- String bodyPartContent = null;
- // INSERT
- if (operation instanceof InsertOperation) {
- InsertOperation op = (InsertOperation) operation;
-
- //TODO: Review code to make sure encoding is correct
- InputStream stream = atomReaderWriter.generateEntityEntry(op.getEntity());
- byte[] bytes = inputStreamToByteArray(stream);
- String content = new String(bytes, "UTF-8");
-
- StringBuilder sb = new StringBuilder();
- sb.append(String.format("POST %s HTTP/1.1\r\n", channel.resource(url).path(op.getTable()).getURI()));
- sb.append(String.format("Content-ID: %d\r\n", contentId++));
- sb.append("Content-Type: application/atom+xml;type=entry\r\n");
- sb.append(String.format("Content-Length: %d\r\n", content.length()));
- sb.append("\r\n");
- sb.append(content);
-
- bodyPartContent = sb.toString();
- }
+ private List<Entry> parseMimeMultipart(ClientResponse response, BatchOperations operations) {
+ List<DataSource> parts = mimeReaderWriter.parseParts(response.getEntityInputStream(), response.getHeaders()
+ .getFirst("Content-Type"));
+
+ if (parts.size() != operations.getOperations().size()) {
+ throw new UniformInterfaceException(String.format(
+ "Batch response from server does not contain the correct amount "
+ + "of parts (expecting %d, received %d instead)", parts.size(), operations.getOperations()
+ .size()), response);
+ }
- if (bodyPartContent != null) {
- bodyPartContents.add(bodyPartContent);
+ List<Entry> result = new ArrayList<Entry>();
+ for (int i = 0; i < parts.size(); i++) {
+ DataSource ds = parts.get(i);
+ Operation operation = operations.getOperations().get(i);
+
+ StatusLine status = httpReaderWriter.parseStatusLine(ds);
+ InternetHeaders headers = httpReaderWriter.parseHeaders(ds);
+ InputStream content = httpReaderWriter.parseEntity(ds);
+
+ if (status.getStatus() >= 400) {
+ // Create dummy client response with status, headers and content
+ InBoundHeaders inBoundHeaders = new InBoundHeaders();
+
+ Enumeration<Header> e = headers.getAllHeaders();
+ while (e.hasMoreElements()) {
+ Header header = e.nextElement();
+ inBoundHeaders.putSingle(header.getName(), header.getValue());
}
- }
- return mimeReaderWriter.getMimeMultipart(bodyPartContents);
+ ClientResponse dummyResponse = new ClientResponse(status.getStatus(), inBoundHeaders, content, null);
+
+ // Wrap into a ServiceException
+ UniformInterfaceException exception = new UniformInterfaceException(dummyResponse);
+ ServiceException serviceException = new ServiceException(exception);
+ serviceException = ServiceExceptionFactory.process("table", serviceException);
+ Error error = new Error().setError(serviceException);
+
+ result.add(error);
+ }
+ else if (operation instanceof InsertEntityOperation) {
+ InsertEntity opResult = new InsertEntity().setEntity(atomReaderWriter.parseEntityEntry(content));
+ result.add(opResult);
+ }
+ else if ((operation instanceof UpdateEntityOperation) || (operation instanceof MergeEntityOperation)
+ || (operation instanceof InsertOrReplaceEntityOperation)
+ || (operation instanceof InsertOrMergeEntityOperation)) {
+ UpdateEntity opResult = new UpdateEntity().setEtag(headers.getHeader("ETag", null));
+ result.add(opResult);
+ }
+ else if (operation instanceof DeleteEntityOperation) {
+ DeleteEntity opResult = new DeleteEntity();
+ result.add(opResult);
+ }
}
- catch (UnsupportedEncodingException e) {
- throw new RuntimeException(e);
+
+ return result;
+ }
+
+ private MimeMultipart createMimeMultipart(BatchOperations operations) {
+ List<DataSource> bodyPartContents = new ArrayList<DataSource>();
+ int contentId = 1;
+ for (Operation operation : operations.getOperations()) {
+
+ DataSource bodyPartContent = null;
+ // INSERT
+ if (operation instanceof InsertEntityOperation) {
+ InsertEntityOperation op = (InsertEntityOperation) operation;
+
+ //
+ // Stream content into byte[] so that we have the length
+ //
+ InputStream stream = atomReaderWriter.generateEntityEntry(op.getEntity());
+ byte[] bytes = inputStreamToByteArray(stream);
+
+ //
+ // Create body of MIME part as the HTTP request
+ //
+ InternetHeaders headers = new InternetHeaders();
+ headers.addHeader("Content-ID", Integer.toString(contentId++));
+ headers.addHeader("Content-Type", "application/atom+xml;type=entry");
+ headers.addHeader("Content-Length", Integer.toString(bytes.length));
+
+ //TODO: Review code to make sure encoding is correct
+ ByteArrayOutputStream httpRequest = new ByteArrayOutputStream();
+ httpReaderWriter.appendMethod(httpRequest, "POST", channel.resource(url).path(op.getTable()).getURI());
+ httpReaderWriter.appendHeaders(httpRequest, headers);
+ httpReaderWriter.appendEntity(httpRequest, new ByteArrayInputStream(bytes));
+
+ bodyPartContent = new InputStreamDataSource(new ByteArrayInputStream(httpRequest.toByteArray()),
+ "application/http");
+ }
+
+ if (bodyPartContent != null) {
+ bodyPartContents.add(bodyPartContent);
+ }
}
+
+ return mimeReaderWriter.getMimeMultipart(bodyPartContents);
}
private byte[] inputStreamToByteArray(InputStream inputStream) {
View
50 microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/models/BatchOperations.java
@@ -15,39 +15,39 @@ public void setOperations(List<Operation> operations) {
}
public BatchOperations addInsertEntity(String table, Entity entity) {
- this.operations.add(new InsertOperation().setTable(table).setEntity(entity));
+ this.operations.add(new InsertEntityOperation().setTable(table).setEntity(entity));
return this;
}
public BatchOperations addUpdateEntity(String table, Entity entity) {
- this.operations.add(new UpdateOperation().setTable(table).setEntity(entity));
+ this.operations.add(new UpdateEntityOperation().setTable(table).setEntity(entity));
return this;
}
public BatchOperations addMergeEntity(String table, Entity entity) {
- this.operations.add(new MergeOperation().setTable(table).setEntity(entity));
+ this.operations.add(new MergeEntityOperation().setTable(table).setEntity(entity));
return this;
}
public BatchOperations addInsertOrReplaceEntity(String table, Entity entity) {
- this.operations.add(new InsertOrReplaceOperation().setTable(table).setEntity(entity));
+ this.operations.add(new InsertOrReplaceEntityOperation().setTable(table).setEntity(entity));
return this;
}
public BatchOperations addInsertOrMergeEntity(String table, Entity entity) {
- this.operations.add(new InsertOrMergeOperation().setTable(table).setEntity(entity));
+ this.operations.add(new InsertOrMergeEntityOperation().setTable(table).setEntity(entity));
return this;
}
public BatchOperations addDeleteEntity(String table, String partitionKey, String rowKey) {
- this.operations.add(new DeleteOperation().setTable(table).setPartitionKey(partitionKey).setRowKey(rowKey));
+ this.operations.add(new DeleteEntityOperation().setTable(table).setPartitionKey(partitionKey).setRowKey(rowKey));
return this;
}
public abstract class Operation {
}
- public class InsertOperation extends Operation {
+ public class InsertEntityOperation extends Operation {
private String table;
private Entity entity;
@@ -55,7 +55,7 @@ public String getTable() {
return table;
}
- public InsertOperation setTable(String table) {
+ public InsertEntityOperation setTable(String table) {
this.table = table;
return this;
}
@@ -64,13 +64,13 @@ public Entity getEntity() {
return entity;
}
- public InsertOperation setEntity(Entity entity) {
+ public InsertEntityOperation setEntity(Entity entity) {
this.entity = entity;
return this;
}
}
- public class UpdateOperation extends Operation {
+ public class UpdateEntityOperation extends Operation {
private String table;
private Entity entity;
@@ -78,7 +78,7 @@ public String getTable() {
return table;
}
- public UpdateOperation setTable(String table) {
+ public UpdateEntityOperation setTable(String table) {
this.table = table;
return this;
}
@@ -87,13 +87,13 @@ public Entity getEntity() {
return entity;
}
- public UpdateOperation setEntity(Entity entity) {
+ public UpdateEntityOperation setEntity(Entity entity) {
this.entity = entity;
return this;
}
}
- public class MergeOperation extends Operation {
+ public class MergeEntityOperation extends Operation {
private String table;
private Entity entity;
@@ -101,7 +101,7 @@ public String getTable() {
return table;
}
- public MergeOperation setTable(String table) {
+ public MergeEntityOperation setTable(String table) {
this.table = table;
return this;
}
@@ -110,13 +110,13 @@ public Entity getEntity() {
return entity;
}
- public MergeOperation setEntity(Entity entity) {
+ public MergeEntityOperation setEntity(Entity entity) {
this.entity = entity;
return this;
}
}
- public class InsertOrReplaceOperation extends Operation {
+ public class InsertOrReplaceEntityOperation extends Operation {
private String table;
private Entity entity;
@@ -124,7 +124,7 @@ public String getTable() {
return table;
}
- public InsertOrReplaceOperation setTable(String table) {
+ public InsertOrReplaceEntityOperation setTable(String table) {
this.table = table;
return this;
}
@@ -133,13 +133,13 @@ public Entity getEntity() {
return entity;
}
- public InsertOrReplaceOperation setEntity(Entity entity) {
+ public InsertOrReplaceEntityOperation setEntity(Entity entity) {
this.entity = entity;
return this;
}
}
- public class InsertOrMergeOperation extends Operation {
+ public class InsertOrMergeEntityOperation extends Operation {
private String table;
private Entity entity;
@@ -147,7 +147,7 @@ public String getTable() {
return table;
}
- public InsertOrMergeOperation setTable(String table) {
+ public InsertOrMergeEntityOperation setTable(String table) {
this.table = table;
return this;
}
@@ -156,13 +156,13 @@ public Entity getEntity() {
return entity;
}
- public InsertOrMergeOperation setEntity(Entity entity) {
+ public InsertOrMergeEntityOperation setEntity(Entity entity) {
this.entity = entity;
return this;
}
}
- public class DeleteOperation extends Operation {
+ public class DeleteEntityOperation extends Operation {
private String table;
private String partitionKey;
private String rowKey;
@@ -171,7 +171,7 @@ public String getTable() {
return table;
}
- public DeleteOperation setTable(String table) {
+ public DeleteEntityOperation setTable(String table) {
this.table = table;
return this;
}
@@ -180,7 +180,7 @@ public String getPartitionKey() {
return partitionKey;
}
- public DeleteOperation setPartitionKey(String partitionKey) {
+ public DeleteEntityOperation setPartitionKey(String partitionKey) {
this.partitionKey = partitionKey;
return this;
}
@@ -189,7 +189,7 @@ public String getRowKey() {
return rowKey;
}
- public DeleteOperation setRowKey(String rowKey) {
+ public DeleteEntityOperation setRowKey(String rowKey) {
this.rowKey = rowKey;
return this;
}
View
60 microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/models/BatchResult.java
@@ -1,5 +1,65 @@
package com.microsoft.windowsazure.services.table.models;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.microsoft.windowsazure.services.core.ServiceException;
+
public class BatchResult {
+ private List<Entry> entries = new ArrayList<Entry>();
+
+ public List<Entry> getEntries() {
+ return entries;
+ }
+
+ public BatchResult setEntries(List<Entry> entries) {
+ this.entries = entries;
+ return this;
+ }
+
+ public static abstract class Entry {
+ }
+
+ public static class InsertEntity extends Entry {
+ private Entity entity;
+
+ public Entity getEntity() {
+ return entity;
+ }
+
+ public InsertEntity setEntity(Entity entity) {
+ this.entity = entity;
+ return this;
+ }
+ }
+
+ public static class UpdateEntity extends Entry {
+ private String etag;
+
+ public String getEtag() {
+ return etag;
+ }
+
+ public UpdateEntity setEtag(String etag) {
+ this.etag = etag;
+ return this;
+ }
+ }
+
+ public static class DeleteEntity extends Entry {
+
+ }
+
+ public static class Error extends Entry {
+ private ServiceException error;
+
+ public ServiceException getError() {
+ return error;
+ }
+ public Error setError(ServiceException error) {
+ this.error = error;
+ return this;
+ }
+ }
}
View
3  ...osoft-azure-api/src/test/java/com/microsoft/windowsazure/services/table/TableServiceIntegrationTest.java
@@ -30,6 +30,7 @@
import com.microsoft.windowsazure.services.core.ServiceException;
import com.microsoft.windowsazure.services.table.models.BatchOperations;
import com.microsoft.windowsazure.services.table.models.BatchResult;
+import com.microsoft.windowsazure.services.table.models.BatchResult.InsertEntity;
import com.microsoft.windowsazure.services.table.models.DeleteEntityOptions;
import com.microsoft.windowsazure.services.table.models.EdmType;
import com.microsoft.windowsazure.services.table.models.Entity;
@@ -650,5 +651,7 @@ public void batchWorks() throws Exception {
// Assert
assertNotNull(result);
+ assertEquals(1, result.getEntries().size());
+ assertEquals(InsertEntity.class, result.getEntries().get(0).getClass());
}
}
Please sign in to comment.
Something went wrong with that request. Please try again.