microsoft-azure-storage/src/com/microsoft/azure/storage/table/MimeHelper.java
static void writeBatchToStream(final OutputStream outStream, final TableRequestOptions options,
            final String tableName, final URI baseUri, final TableBatchOperation batch, final String batchID,
            final String changeSet, final OperationContext opContext) throws IOException, URISyntaxException,
            StorageException {
        final OutputStreamWriter outWriter = new OutputStreamWriter(outStream, Constants.UTF8_CHARSET);

        MimePart mimePart;
        int contentID = 0;
        boolean isQuery = batch.size() == 1 && batch.get(0).getOperationType() == TableOperationType.RETRIEVE;

        // when batch is made, a check is done to make sure only one retrieve is added
        if (isQuery) {
            final QueryTableOperation qOp = (QueryTableOperation) batch.get(0);
            // Write MIME batch Header
            MimeHelper.writeMIMEBoundary(outWriter, batchID);

            mimePart = new MimePart();
            mimePart.op = qOp.getOperationType();

            UriQueryBuilder builder = new UriQueryBuilder();
            mimePart.requestIdentity = builder.addToURI(PathUtility.appendPathToSingleUri(baseUri,
                    qOp.generateRequestIdentityWithTable(tableName)));

            mimePart.headers.put(Constants.HeaderConstants.ACCEPT,
                    generateAcceptHeaderValue(options.getTablePayloadFormat()));
            mimePart.headers.put(TableConstants.HeaderConstants.MAX_DATA_SERVICE_VERSION,
                    TableConstants.HeaderConstants.MAX_DATA_SERVICE_VERSION_VALUE);

            outWriter.write(mimePart.toRequestString());
        }
        else {
            // Write MIME batch Header
            MimeHelper.writeMIMEBoundary(outWriter, batchID);
            MimeHelper.writeMIMEContentType(outWriter, changeSet);
            outWriter.write("\r\n");

            // Write each operation
            for (final TableOperation op : batch) {
                // New mime part for changeset
                MimeHelper.writeMIMEBoundary(outWriter, changeSet);

                mimePart = new MimePart();
                mimePart.op = op.getOperationType();

                UriQueryBuilder builder = new UriQueryBuilder();
                mimePart.requestIdentity = builder.addToURI(PathUtility.appendPathToSingleUri(baseUri,
                        op.generateRequestIdentityWithTable(tableName)));

                mimePart.headers.put(TableConstants.HeaderConstants.CONTENT_ID, Integer.toString(contentID));
                mimePart.headers.put(Constants.HeaderConstants.ACCEPT,
                        generateAcceptHeaderValue(options.getTablePayloadFormat()));
                mimePart.headers.put(TableConstants.HeaderConstants.MAX_DATA_SERVICE_VERSION,
                        TableConstants.HeaderConstants.MAX_DATA_SERVICE_VERSION_VALUE);

                if (op.getOperationType() == TableOperationType.INSERT_OR_MERGE
                        || op.getOperationType() == TableOperationType.MERGE) {
                    // post tunnelling
                    mimePart.headers.put(TableConstants.HeaderConstants.X_HTTP_METHOD,
                            TableOperationType.MERGE.toString());
                }

                // etag
                if (op.getOperationType() == TableOperationType.DELETE
                        || op.getOperationType() == TableOperationType.REPLACE
                        || op.getOperationType() == TableOperationType.MERGE) {
                    if (op.getEntity() != null && op.getEntity().getEtag() != null) {
                        mimePart.headers.put(Constants.HeaderConstants.IF_MATCH, op.getEntity().getEtag());
                    }
                }

                // prefer header
                if (op.getOperationType() == TableOperationType.INSERT) {
                    mimePart.headers.put(TableConstants.HeaderConstants.PREFER,
                            op.getEchoContent() ? TableConstants.HeaderConstants.RETURN_CONTENT
                                    : TableConstants.HeaderConstants.RETURN_NO_CONTENT);
                }

                if (op.getOperationType() != TableOperationType.DELETE) {
                    mimePart.headers.put(Constants.HeaderConstants.CONTENT_TYPE,
                            TableConstants.HeaderConstants.JSON_CONTENT_TYPE);
                    mimePart.payload = writeStringForOperation(op, options.getTablePayloadFormat(), opContext);
                    mimePart.headers.put(Constants.HeaderConstants.CONTENT_LENGTH,
                            Integer.toString(mimePart.payload.getBytes(Constants.UTF8_CHARSET).length));
                }

                // write the request (no body)
                outWriter.write(mimePart.toRequestString());

                contentID = contentID + 1;
            }
        }

        if (!isQuery) {
            // end changeset
            MimeHelper.writeMIMEBoundaryClosure(outWriter, changeSet);
        }
        // end batch
        MimeHelper.writeMIMEBoundaryClosure(outWriter, batchID);

        outWriter.flush();
    }
static void writeBatchToStream(final OutputStream outStream, final TableRequestOptions options,
            final String tableName, final URI baseUri, final TableBatchOperation batch, final String batchID,
            final String changeSet, final OperationContext opContext) throws IOException, URISyntaxException,
            StorageException {
        final OutputStreamWriter outWriter = new OutputStreamWriter(outStream, Constants.UTF8_CHARSET);

        MimePart mimePart;
        int contentID = 0;
        boolean isQuery = batch.size() == 1 && batch.get(0).getOperationType() == TableOperationType.RETRIEVE;

        // when batch is made, a check is done to make sure only one retrieve is added
        if (isQuery) {
            final QueryTableOperation qOp = (QueryTableOperation) batch.get(0);
            // Write MIME batch Header
            MimeHelper.writeMIMEBoundary(outWriter, batchID);

            mimePart = new MimePart();
            mimePart.op = qOp.getOperationType();

            UriQueryBuilder builder = new UriQueryBuilder();
            mimePart.requestIdentity = builder.addToURI(PathUtility.appendPathToSingleUri(baseUri,
                    qOp.generateRequestIdentityWithTable(tableName)));

            mimePart.headers.put(Constants.HeaderConstants.ACCEPT,
                    generateAcceptHeaderValue(options.getTablePayloadFormat()));
            mimePart.headers.put(TableConstants.HeaderConstants.MAX_DATA_SERVICE_VERSION,
                    TableConstants.HeaderConstants.MAX_DATA_SERVICE_VERSION_VALUE);

            outWriter.write(mimePart.toRequestString());
        }
        else {
            // Write MIME batch Header
            MimeHelper.writeMIMEBoundary(outWriter, batchID);
            MimeHelper.writeMIMEContentType(outWriter, changeSet);
            outWriter.write("\r\n");

            // Write each operation
            for (final TableOperation op : batch) {
                // New mime part for changeset
                MimeHelper.writeMIMEBoundary(outWriter, changeSet);

                mimePart = new MimePart();
                mimePart.op = op.getOperationType();

                UriQueryBuilder builder = new UriQueryBuilder();
                mimePart.requestIdentity = builder.addToURI(PathUtility.appendPathToSingleUri(baseUri,
                        op.generateRequestIdentityWithTable(tableName)));

                mimePart.headers.put(TableConstants.HeaderConstants.CONTENT_ID, Integer.toString(contentID));
                mimePart.headers.put(Constants.HeaderConstants.ACCEPT,
                        generateAcceptHeaderValue(options.getTablePayloadFormat()));
                mimePart.headers.put(TableConstants.HeaderConstants.MAX_DATA_SERVICE_VERSION,
                        TableConstants.HeaderConstants.MAX_DATA_SERVICE_VERSION_VALUE);

                if (op.getOperationType() == TableOperationType.INSERT_OR_MERGE
                        || op.getOperationType() == TableOperationType.MERGE) {
                    // post tunnelling
                    mimePart.headers.put(TableConstants.HeaderConstants.X_HTTP_METHOD,
                            TableOperationType.MERGE.toString());
                }

                // etag
                if (op.getOperationType() == TableOperationType.DELETE
                        || op.getOperationType() == TableOperationType.REPLACE
                        || op.getOperationType() == TableOperationType.MERGE) {
                    if (op.getEntity() != null && op.getEntity().getEtag() != null) {
                        mimePart.headers.put(Constants.HeaderConstants.IF_MATCH, op.getEntity().getEtag());
                    }
                }

                // prefer header
                if (op.getOperationType() == TableOperationType.INSERT) {
                    mimePart.headers.put(TableConstants.HeaderConstants.PREFER,
                            op.getEchoContent() ? TableConstants.HeaderConstants.RETURN_CONTENT
                                    : TableConstants.HeaderConstants.RETURN_NO_CONTENT);
                }

                if (op.getOperationType() != TableOperationType.DELETE) {
                    mimePart.headers.put(Constants.HeaderConstants.CONTENT_TYPE,
                            TableConstants.HeaderConstants.JSON_CONTENT_TYPE);
                    mimePart.payload = writeStringForOperation(op, options.getTablePayloadFormat(), opContext);
                    mimePart.headers.put(Constants.HeaderConstants.CONTENT_LENGTH,
                            Integer.toString(mimePart.payload.getBytes(Constants.UTF8_CHARSET).length));
                }

                // write the request (no body)
                outWriter.write(mimePart.toRequestString());

                contentID = contentID + 1;
            }
        }

        if (!isQuery) {
            // end changeset
            MimeHelper.writeMIMEBoundaryClosure(outWriter, changeSet);
        }
        // end batch
        MimeHelper.writeMIMEBoundaryClosure(outWriter, batchID);

        outWriter.flush();
    }
Reserved for internal use. Writes the batch operation to the output stream using batch request syntax.
Batch request syntax is described in the MSDN topic <a
href="http://msdn.microsoft.com/en-us/library/azure/dd894038.aspx">Performing Entity Group
Transactions</a>.

@param outStream
The {@link OutputStream} to write the batch request to.
@param tableName
A <code>String</code> containing the name of the table to apply each operation to.
@param batch
A {@link TableBatchOperation} containing the operations to write to the output stream
@param batchID
A <code>String</code> containing the identifier to use as the MIME boundary for the batch request.
@param changeSet
A <code>String</code> containing the identifier to use as the MIME boundary for operations within the
batch.
@param opContext
An {@link OperationContext} object for tracking the current operation. Specify <code>null</code> to
safely ignore operation context.
@throws IOException
if an IO error occurs.
@throws URISyntaxException
if an invalid URI is used.
@throws StorageException
if an error occurs accessing the Storage service.