You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by ch...@apache.org on 2014/10/06 13:58:27 UTC
[1/4] git commit: Code Review - Bug fix and refactoring
Repository: olingo-odata2
Updated Branches:
refs/heads/olingo436BatchRefactoring ffb21db2d -> f0dc0f745
Code Review - Bug fix and refactoring
Signed-off-by: Christian Amend <ch...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata2/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata2/commit/1f90b733
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata2/tree/1f90b733
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata2/diff/1f90b733
Branch: refs/heads/olingo436BatchRefactoring
Commit: 1f90b733a25a41c43f93ceb0f78369e6c27ef753
Parents: ffb21db
Author: Christian Holzer <c....@sap.com>
Authored: Thu Oct 2 19:12:38 2014 +0200
Committer: Christian Amend <ch...@apache.org>
Committed: Mon Oct 6 13:54:37 2014 +0200
----------------------------------------------------------------------
.../olingo/odata2/core/batch/AcceptParser.java | 64 +++++--
.../odata2/core/batch/v2/BatchBodyPart.java | 27 +--
.../odata2/core/batch/v2/BatchChangeSet.java | 55 ------
.../core/batch/v2/BatchChangeSetPart.java | 55 ++++++
.../odata2/core/batch/v2/BatchParser.java | 2 +-
.../odata2/core/batch/v2/BatchParserCommon.java | 122 +++++++------
.../core/batch/v2/BatchQueryOperation.java | 10 +-
.../batch/v2/BatchRequestTransformator.java | 16 +-
.../batch/v2/BatchResponseTransformator.java | 13 +-
.../core/batch/v2/BatchTransformatorCommon.java | 24 +--
.../odata2/core/batch/AcceptParserTest.java | 77 +++++---
.../core/batch/BatchParserCommonTest.java | 182 +++++++++++++++----
.../core/batch/BatchRequestParserTest.java | 124 +++++++++----
.../batch/BatchTransformatorCommonTest.java | 12 +-
14 files changed, 516 insertions(+), 267 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/1f90b733/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/AcceptParser.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/AcceptParser.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/AcceptParser.java
index 946fccf..48bfb1b 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/AcceptParser.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/AcceptParser.java
@@ -6,9 +6,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -20,6 +20,7 @@ package org.apache.olingo.odata2.core.batch;
import java.util.ArrayList;
import java.util.Comparator;
+import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
@@ -30,10 +31,11 @@ import java.util.regex.Pattern;
import org.apache.olingo.odata2.api.batch.BatchException;
/**
- *
+ *
*/
public class AcceptParser {
+ private static final String COMMA = ",";
private static final String BAD_REQUEST = "400";
private static final String ALL = "*";
private static final String REG_EX_QUALITY_FACTOR = "q=((?:1\\.0{0,3})|(?:0\\.[0-9]{0,2}[1-9]))";
@@ -48,10 +50,15 @@ public class AcceptParser {
private static final double QUALITY_PARAM_FACTOR = 0.001;
- public static List<String> parseAcceptHeaders(final String headerValue) throws BatchException {
- TreeSet<Accept> acceptTree = getAcceptTree();
- List<String> acceptHeaders = new ArrayList<String>();
- Scanner acceptHeaderScanner = new Scanner(headerValue);
+ private List<String> acceptHeaderValues = new ArrayList<String>();
+ private List<String> acceptLanguageHeaderValues = new ArrayList<String>();
+
+ public List<String> parseAcceptHeaders() throws BatchException {
+ final String headerValue = concatenateHeaderLines(acceptHeaderValues);
+ final TreeSet<Accept> acceptTree = getAcceptTree();
+ final List<String> acceptHeaders = new ArrayList<String>();
+ final Scanner acceptHeaderScanner = new Scanner(headerValue);
+
acceptHeaderScanner.useDelimiter(",\\s?");
while (acceptHeaderScanner.hasNext()) {
if (acceptHeaderScanner.hasNext(REG_EX_ACCEPT_WITH_Q_FACTOR)) {
@@ -75,18 +82,21 @@ public class AcceptParser {
}
}
for (Accept accept : acceptTree) {
- acceptHeaders.add(accept.getValue());
+ if (!acceptHeaders.contains(accept.getValue())) {
+ acceptHeaders.add(accept.getValue());
+ }
}
acceptHeaderScanner.close();
return acceptHeaders;
}
- private static double getQualityFactor(final String acceptHeaderValue, double qualityFactor) {
+ private double getQualityFactor(final String acceptHeaderValue, double qualityFactor) {
int paramNumber = 0;
double typeFactor = 0.0;
double subtypeFactor = 0.0;
String[] mediaRange = acceptHeaderValue.split("(?=[^;]+);");
String[] mediaTypes = mediaRange[0].split("/");
+
if (mediaTypes.length == 2) {
String type = mediaTypes[0];
String subtype = mediaTypes[1];
@@ -101,13 +111,15 @@ public class AcceptParser {
String[] parameters = mediaRange[1].split(";\\s?");
paramNumber = parameters.length;
}
+
qualityFactor = qualityFactor + paramNumber * QUALITY_PARAM_FACTOR + typeFactor + subtypeFactor;
return qualityFactor;
}
- public static List<String> parseAcceptableLanguages(final String headerValue) throws BatchException {
- List<String> acceptLanguages = new LinkedList<String>();
- TreeSet<Accept> acceptTree = getAcceptTree();
+ public List<String> parseAcceptableLanguages() throws BatchException {
+ final String headerValue = concatenateHeaderLines(acceptLanguageHeaderValues);
+ final List<String> acceptLanguages = new LinkedList<String>();
+ final TreeSet<Accept> acceptTree = getAcceptTree();
Scanner acceptLanguageScanner = new Scanner(headerValue);
acceptLanguageScanner.useDelimiter(",\\s?");
@@ -132,13 +144,37 @@ public class AcceptParser {
}
}
for (Accept accept : acceptTree) {
- acceptLanguages.add(accept.getValue());
+ if (!acceptLanguages.contains(accept.getValue())) {
+ acceptLanguages.add(accept.getValue());
+ }
}
acceptLanguageScanner.close();
return acceptLanguages;
}
- private static TreeSet<Accept> getAcceptTree() {
+ private String concatenateHeaderLines(final List<String> headerValues) {
+ final StringBuilder builder = new StringBuilder();
+ final Iterator<String> iter = headerValues.iterator();
+
+ while (iter.hasNext()) {
+ builder.append(iter.next());
+ if (iter.hasNext()) {
+ builder.append(COMMA);
+ }
+ }
+
+ return builder.toString();
+ }
+
+ public void addAcceptHeaderValue(final String headerValue) {
+ acceptHeaderValues.add(headerValue);
+ }
+
+ public void addAcceptLanguageHeaderValue(final String headerValue) {
+ acceptLanguageHeaderValues.add(headerValue);
+ }
+
+ private TreeSet<Accept> getAcceptTree() {
TreeSet<Accept> treeSet = new TreeSet<Accept>(new Comparator<Accept>() {
@Override
public int compare(final Accept o1, final Accept o2) {
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/1f90b733/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchBodyPart.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchBodyPart.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchBodyPart.java
index e355f84..4edcf45 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchBodyPart.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchBodyPart.java
@@ -24,18 +24,16 @@ import java.util.Locale;
import java.util.Map;
import org.apache.olingo.odata2.api.batch.BatchException;
-import org.apache.olingo.odata2.api.commons.HttpContentType;
import org.apache.olingo.odata2.api.commons.HttpHeaders;
import org.apache.olingo.odata2.core.batch.v2.BatchParserCommon.HeaderField;
-import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
public class BatchBodyPart implements BatchPart {
- final private Map<String, HeaderField> headers;
final private String boundary;
- final private boolean isChangeSet;
final private boolean isStrict;
- final private List<String> body;
- private boolean isParsed = false;
+ final List<String> remainingMessage = new LinkedList<String>();
+
+ private Map<String, HeaderField> headers;
+ private boolean isChangeSet;
private List<BatchQueryOperation> requests;
public BatchBodyPart(final List<String> bodyPartMessage, final String boundary, final boolean isStrict)
@@ -43,19 +41,14 @@ public class BatchBodyPart implements BatchPart {
this.boundary = boundary;
this.isStrict = isStrict;
- List<String> remainingMessage = new LinkedList<String>();
remainingMessage.addAll(bodyPartMessage);
+ }
+ public BatchBodyPart parse() throws BatchException {
headers = BatchParserCommon.consumeHeaders(remainingMessage);
BatchParserCommon.consumeBlankLine(remainingMessage, isStrict);
isChangeSet = isChangeSet(headers);
- body = remainingMessage;
- }
-
- public BatchBodyPart parse(final int contentLength) throws BatchException {
- List<String> remainingMessage = BatchParserCommon.trimStringListToLength(body, contentLength);
requests = consumeRequest(remainingMessage);
- isParsed = true;
return this;
}
@@ -78,7 +71,7 @@ public class BatchBodyPart implements BatchPart {
}
private boolean isContentTypeMultiPartMixed(final String contentType) {
- return contentType.contains(HttpContentType.MULTIPART_MIXED);
+ return BatchParserCommon.PATTERN_MULTIPART_BOUNDARY.matcher(contentType).matches();
}
private List<BatchQueryOperation> consumeRequest(final List<String> remainingMessage) throws BatchException {
@@ -95,7 +88,7 @@ public class BatchBodyPart implements BatchPart {
final List<BatchQueryOperation> requestList = new LinkedList<BatchQueryOperation>();
for (List<String> changeRequest : changeRequests) {
- requestList.add(new BatchChangeSet(changeRequest, isStrict).parse());
+ requestList.add(new BatchChangeSetPart(changeRequest, isStrict).parse());
}
return requestList;
@@ -146,10 +139,6 @@ public class BatchBodyPart implements BatchPart {
}
public List<BatchQueryOperation> getRequests() {
- if (!isParsed) {
- throw new ODataRuntimeException("Batch part must be parsed first");
- }
-
return requests;
}
}
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/1f90b733/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchChangeSet.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchChangeSet.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchChangeSet.java
deleted file mode 100644
index 5331ff8..0000000
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchChangeSet.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*******************************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- ******************************************************************************/
-package org.apache.olingo.odata2.core.batch.v2;
-
-import java.util.List;
-
-import org.apache.olingo.odata2.api.batch.BatchException;
-
-public class BatchChangeSet extends BatchQueryOperation {
- private BatchQueryOperation request;
-
- public BatchChangeSet(final List<String> message, final boolean isStrict) throws BatchException {
- super(message, isStrict);
- }
-
- @Override
- public BatchChangeSet parse() throws BatchException {
- headers = BatchParserCommon.consumeHeaders(message);
- BatchParserCommon.consumeBlankLine(message, isStrict);
-
- request = new BatchQueryOperation(message, isStrict).parse();
-
- return this;
- }
-
- public BatchQueryOperation getRequest() {
- return request;
- }
-
- @Override
- public List<String> getBody() {
- return request.getBody();
- }
-
- @Override
- public String getHttpMethod() {
- return request.getHttpMethod();
- }
-}
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/1f90b733/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchChangeSetPart.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchChangeSetPart.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchChangeSetPart.java
new file mode 100644
index 0000000..746c368
--- /dev/null
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchChangeSetPart.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.core.batch.v2;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.batch.BatchException;
+
+public class BatchChangeSetPart extends BatchQueryOperation {
+ private BatchQueryOperation request;
+
+ public BatchChangeSetPart(final List<String> message, final boolean isStrict) throws BatchException {
+ super(message, isStrict);
+ }
+
+ @Override
+ public BatchChangeSetPart parse() throws BatchException {
+ headers = BatchParserCommon.consumeHeaders(message);
+ BatchParserCommon.consumeBlankLine(message, isStrict);
+
+ request = new BatchQueryOperation(message, isStrict).parse();
+
+ return this;
+ }
+
+ public BatchQueryOperation getRequest() {
+ return request;
+ }
+
+ @Override
+ public List<String> getBody() {
+ return request.getBody();
+ }
+
+ @Override
+ public String getHttpStatusLine() {
+ return request.getHttpStatusLine();
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/1f90b733/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchParser.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchParser.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchParser.java
index b64453b..6fb7dbd 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchParser.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchParser.java
@@ -83,7 +83,7 @@ public class BatchParser {
final List<List<String>> bodyPartStrings = splitBodyParts(in, boundary);
for (List<String> bodyPartString : bodyPartStrings) {
- BatchBodyPart bodyPart = new BatchBodyPart(bodyPartString, boundary, isStrict);
+ BatchBodyPart bodyPart = new BatchBodyPart(bodyPartString, boundary, isStrict).parse();
resultList.addAll(transformator.transform(bodyPart, batchRequestPathInfo, baseUri));
}
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/1f90b733/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchParserCommon.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchParserCommon.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchParserCommon.java
index 51314dd..8b7f62a 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchParserCommon.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchParserCommon.java
@@ -44,32 +44,23 @@ import org.apache.olingo.odata2.core.batch.AcceptParser;
import org.apache.olingo.odata2.core.commons.Decoder;
public class BatchParserCommon {
- private static final String BOUNDARY_IDENTIFIER = "boundary=";
private static final String REG_EX_BOUNDARY =
"([a-zA-Z0-9_\\-\\.'\\+]{1,70})|\"([a-zA-Z0-9_\\-\\.'\\+\\s\\" +
"(\\),/:=\\?]{1,69}[a-zA-Z0-9_\\-\\.'\\+\\(\\),/:=\\?])\""; // See RFC 2046
- private static final Pattern REG_EX_HEADER = Pattern.compile("([a-zA-Z\\-]+):\\s?(.*)\\s*");
+ private static final String REX_EX_MULTIPART_BOUNDARY = "multipart/mixed;\\s*boundary=(.+)";
+ private static final String REG_EX_APPLICATION_HTTP = "application/http";
+ public static final Pattern PATTERN_MULTIPART_BOUNDARY = Pattern.compile(REX_EX_MULTIPART_BOUNDARY,
+ Pattern.CASE_INSENSITIVE);
+ public static final Pattern PATTERN_HEADER_LINE = Pattern.compile("([a-zA-Z\\-]+):\\s?(.*)\\s*");
+ public static final Pattern PATTERN_CONTENT_TYPE_APPLICATION_HTTP = Pattern.compile(REG_EX_APPLICATION_HTTP,
+ Pattern.CASE_INSENSITIVE);
- public static List<String> trimStringListToLength(final List<String> list, final int length) {
- final Iterator<String> iter = list.iterator();
- final List<String> result = new ArrayList<String>();
- boolean isEndReached = false;
- int currentLength = 0;
-
- while (!isEndReached && iter.hasNext()) {
- String currentLine = iter.next();
-
- if (currentLength + currentLine.length() <= length) {
- result.add(currentLine);
- currentLength += currentLine.length();
- } else {
- result.add(currentLine.substring(0, length - currentLength));
- isEndReached = true;
- }
- }
+ public static String trimStringListToStringLength(final List<String> list, final int length) {
+ final String message = stringListToString(list);
+ final int lastIndex = Math.min(length, message.length());
- return result;
+ return (lastIndex > 0) ? message.substring(0, lastIndex) : "";
}
public static String stringListToString(final List<String> list) {
@@ -82,13 +73,21 @@ public class BatchParserCommon {
return builder.toString();
}
- public static InputStream convertMessageToInputStream(final List<String> message, final int contentLength)
+ public static InputStream convertMessageToInputStream(final List<String> messageList, final int contentLength)
throws BatchException {
- List<String> shortenedMessage = BatchParserCommon.trimStringListToLength(message, contentLength);
+ final String message = trimStringListToStringLength(messageList, contentLength);
- return new ByteArrayInputStream(BatchParserCommon.stringListToString(shortenedMessage).getBytes());
+ return new ByteArrayInputStream(message.getBytes());
}
+ public static InputStream convertMessageToInputStream(final List<String> messageList)
+ throws BatchException {
+ final String message = stringListToString(messageList);
+
+ return new ByteArrayInputStream(message.getBytes());
+ }
+
+ // TODO Splitten von InputStream, sodass nur eine Iteration erfolgen muss
static List<List<String>> splitMessageByBoundary(final List<String> message, final String boundary)
throws BatchException {
final List<List<String>> messageParts = new LinkedList<List<String>>();
@@ -149,15 +148,16 @@ public class BatchParserCommon {
}
}
- static Map<String, HeaderField> consumeHeaders(final List<String> remainingMessage) throws BatchException {
+ public static Map<String, HeaderField> consumeHeaders(final List<String> remainingMessage) throws BatchException {
final Map<String, HeaderField> headers = new HashMap<String, HeaderField>();
boolean isHeader = true;
+ final Iterator<String> iter = remainingMessage.iterator();
+ final AcceptParser acceptParser = new AcceptParser();
String currentLine;
- Iterator<String> iter = remainingMessage.iterator();
while (iter.hasNext() && isHeader) {
currentLine = iter.next();
- Matcher headerMatcher = REG_EX_HEADER.matcher(currentLine);
+ Matcher headerMatcher = PATTERN_HEADER_LINE.matcher(currentLine);
if (headerMatcher.matches() && headerMatcher.groupCount() == 2) {
iter.remove();
@@ -167,38 +167,55 @@ public class BatchParserCommon {
String headerValue = headerMatcher.group(2).trim();
if (HttpHeaders.ACCEPT.equalsIgnoreCase(headerNameLowerCase)) {
- List<String> acceptHeaders = AcceptParser.parseAcceptHeaders(headerValue);
- headers.put(headerNameLowerCase, new HeaderField(headerName, acceptHeaders));
+ acceptParser.addAcceptHeaderValue(headerValue);
} else if (HttpHeaders.ACCEPT_LANGUAGE.equalsIgnoreCase(headerNameLowerCase)) {
- List<String> acceptLanguageHeaders = AcceptParser.parseAcceptableLanguages(headerValue);
- headers.put(headerNameLowerCase, new HeaderField(headerName, acceptLanguageHeaders));
+ acceptParser.addAcceptLanguageHeaderValue(headerValue);
} else {
- HeaderField headerField = headers.get(headerNameLowerCase);
- headerField = headerField == null ? new HeaderField(headerName) : headerField;
- headers.put(headerNameLowerCase, headerField);
- headerField.getValues().add(headerValue);
+ addHeaderValue(headers, headerName, headerNameLowerCase, headerValue);
}
} else {
isHeader = false;
}
}
+ final List<String> acceptHeader = acceptParser.parseAcceptHeaders();
+ headers.put(HttpHeaders.ACCEPT.toLowerCase(), new HeaderField(HttpHeaders.ACCEPT, acceptHeader));
+
+ final List<String> acceptLanguageHeader = acceptParser.parseAcceptableLanguages();
+ headers.put(HttpHeaders.ACCEPT_LANGUAGE.toLowerCase(), new HeaderField(HttpHeaders.ACCEPT_LANGUAGE,
+ acceptLanguageHeader));
+
return Collections.unmodifiableMap(headers);
}
- static void consumeBlankLine(final List<String> remainingMessage, final boolean isStrict) throws BatchException {
- if (remainingMessage.size() > 0 && "".equals(remainingMessage.get(0).trim())) {
- remainingMessage.remove(0);
- } else {
- if (isStrict) {
- throw new BatchException(BatchException.MISSING_BLANK_LINE);
+ private static void addHeaderValue(final Map<String, HeaderField> headers, final String headerName,
+ final String headerNameLowerCase, final String headerValue) {
+ HeaderField headerField = headers.get(headerNameLowerCase);
+ headerField = headerField == null ? new HeaderField(headerName) : headerField;
+ headers.put(headerNameLowerCase, headerField);
+
+ for (final String singleValue : splitHeaderValuesByComma(headerValue)) {
+ if (!headerField.getValues().contains(singleValue)) {
+ headerField.getValues().add(singleValue);
}
}
}
- static void consumeLastBlankLine(final List<String> message, final boolean isStrict) throws BatchException {
- if (message.size() > 0 && "".equals(message.get(message.size() - 1).trim())) {
- message.remove(message.size() - 1);
+ private static List<String> splitHeaderValuesByComma(final String headerValue) {
+ final List<String> singleValues = new ArrayList<String>();
+
+ String[] parts = headerValue.split(",");
+ for (final String value : parts) {
+ singleValues.add(value.trim());
+ }
+
+ return singleValues;
+ }
+
+ public static void consumeBlankLine(final List<String> remainingMessage, final boolean isStrict)
+ throws BatchException {
+ if (remainingMessage.size() > 0 && "".equals(remainingMessage.get(0).trim())) {
+ remainingMessage.remove(0);
} else {
if (isStrict) {
throw new BatchException(BatchException.MISSING_BLANK_LINE);
@@ -206,25 +223,22 @@ public class BatchParserCommon {
}
}
- static String getBoundary(final String contentType) throws BatchException {
- if (contentType.contains(HttpContentType.MULTIPART_MIXED)) {
- String[] parts = contentType.split(BOUNDARY_IDENTIFIER);
+ public static String getBoundary(final String contentType) throws BatchException {
+ final Matcher boundaryMatcher = PATTERN_MULTIPART_BOUNDARY.matcher(contentType);
- if (parts.length == 2) {
- if (parts[1].matches(REG_EX_BOUNDARY)) {
- return trimQuota(parts[1].trim());
- } else {
- throw new BatchException(BatchException.INVALID_BOUNDARY);
- }
+ if (boundaryMatcher.matches()) {
+ final String boundary = boundaryMatcher.group(1);
+ if (boundary.matches(REG_EX_BOUNDARY)) {
+ return trimQuota(boundary);
} else {
- throw new BatchException(BatchException.MISSING_PARAMETER_IN_CONTENT_TYPE);
+ throw new BatchException(BatchException.INVALID_BOUNDARY);
}
} else {
throw new BatchException(BatchException.INVALID_CONTENT_TYPE.addContent(HttpContentType.MULTIPART_MIXED));
}
}
- static Map<String, List<String>> parseQueryParameter(final String httpRequest) {
+ public static Map<String, List<String>> parseQueryParameter(final String httpRequest) {
Map<String, List<String>> queryParameter = new HashMap<String, List<String>>();
String[] requestParts = httpRequest.split(" ");
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/1f90b733/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchQueryOperation.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchQueryOperation.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchQueryOperation.java
index 179fffb..5176bb8 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchQueryOperation.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchQueryOperation.java
@@ -27,7 +27,7 @@ import org.apache.olingo.odata2.core.batch.v2.BatchParserCommon.HeaderField;
public class BatchQueryOperation implements BatchPart {
protected final boolean isStrict;
- protected String httpMethod;
+ protected String httpStatusLine;
protected Map<String, HeaderField> headers;
protected List<String> body;
protected int bodySize;
@@ -39,7 +39,7 @@ public class BatchQueryOperation implements BatchPart {
}
public BatchQueryOperation parse() throws BatchException {
- httpMethod = consumeHttpMethod(message);
+ httpStatusLine = consumeHttpStatusLine(message);
headers = BatchParserCommon.consumeHeaders(message);
BatchParserCommon.consumeBlankLine(message, isStrict);
body = message;
@@ -47,7 +47,7 @@ public class BatchQueryOperation implements BatchPart {
return this;
}
- protected String consumeHttpMethod(final List<String> message) throws BatchException {
+ protected String consumeHttpStatusLine(final List<String> message) throws BatchException {
if (message.size() > 0 && !message.get(0).trim().equals("")) {
String method = message.get(0);
message.remove(0);
@@ -58,8 +58,8 @@ public class BatchQueryOperation implements BatchPart {
}
}
- public String getHttpMethod() {
- return httpMethod;
+ public String getHttpStatusLine() {
+ return httpStatusLine;
}
public List<String> getBody() {
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/1f90b733/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchRequestTransformator.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchRequestTransformator.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchRequestTransformator.java
index 3626686..5169575 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchRequestTransformator.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchRequestTransformator.java
@@ -55,7 +55,6 @@ public class BatchRequestTransformator implements BatchTransformator {
final List<ODataRequest> requests = new LinkedList<ODataRequest>();
final List<BatchParserResult> resultList = new ArrayList<BatchParserResult>();
- BatchTransformatorCommon.parsePartSyntax(bodyPart);
validateBodyPartHeaders(bodyPart);
for (BatchQueryOperation queryOperation : bodyPart.getRequests()) {
@@ -77,7 +76,7 @@ public class BatchRequestTransformator implements BatchTransformator {
final String baseUri, final BatchQueryOperation queryOperation) throws BatchException {
if (bodyPart.isChangeSet()) {
- BatchQueryOperation encapsulatedQueryOperation = ((BatchChangeSet) queryOperation).getRequest();
+ BatchQueryOperation encapsulatedQueryOperation = ((BatchChangeSetPart) queryOperation).getRequest();
Map<String, HeaderField> headers = transformHeader(encapsulatedQueryOperation, queryOperation);
validateChangeSetMultipartMimeHeaders(queryOperation, encapsulatedQueryOperation);
@@ -98,7 +97,7 @@ public class BatchRequestTransformator implements BatchTransformator {
private ODataRequest createRequest(final BatchQueryOperation operation, final Map<String, HeaderField> headers,
final PathInfo pathInfo, final String baseUri, final boolean isChangeSet) throws BatchException {
- ODataHttpMethod httpMethod = getHttpMethod(operation.getHttpMethod());
+ ODataHttpMethod httpMethod = getHttpMethod(operation.getHttpStatusLine());
validateHttpMethod(httpMethod, isChangeSet);
validateBody(httpMethod, operation);
InputStream bodyStrean = getBodyStream(operation, headers, httpMethod);
@@ -106,10 +105,10 @@ public class BatchRequestTransformator implements BatchTransformator {
ODataRequestBuilder requestBuilder = ODataRequest.method(httpMethod)
.acceptableLanguages(getAcceptLanguageHeaders(headers))
.acceptHeaders(getAcceptHeaders(headers))
- .allQueryParameters(BatchParserCommon.parseQueryParameter(operation.getHttpMethod()))
+ .allQueryParameters(BatchParserCommon.parseQueryParameter(operation.getHttpStatusLine()))
.body(bodyStrean)
.requestHeaders(BatchParserCommon.headerFieldMapToMultiMap(headers))
- .pathInfo(BatchParserCommon.parseRequestUri(operation.getHttpMethod(), pathInfo, baseUri));
+ .pathInfo(BatchParserCommon.parseRequestUri(operation.getHttpStatusLine(), pathInfo, baseUri));
addContentTypeHeader(requestBuilder, headers);
@@ -135,9 +134,12 @@ public class BatchRequestTransformator implements BatchTransformator {
return new ByteArrayInputStream(new byte[0]);
} else {
int contentLength = BatchTransformatorCommon.getContentLength(headers);
- contentLength = (contentLength >= 0) ? contentLength : Integer.MAX_VALUE;
- return BatchParserCommon.convertMessageToInputStream(operation.getBody(), contentLength);
+ if (contentLength == -1) {
+ return BatchParserCommon.convertMessageToInputStream(operation.getBody());
+ } else {
+ return BatchParserCommon.convertMessageToInputStream(operation.getBody(), contentLength);
+ }
}
}
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/1f90b733/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchResponseTransformator.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchResponseTransformator.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchResponseTransformator.java
index 88f5064..d82d09e 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchResponseTransformator.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchResponseTransformator.java
@@ -51,7 +51,6 @@ public class BatchResponseTransformator implements BatchTransformator {
List<BatchParserResult> resultList = new ArrayList<BatchParserResult>();
- BatchTransformatorCommon.parsePartSyntax(bodyPart);
BatchTransformatorCommon.validateContentType(bodyPart.getHeaders());
resultList.addAll(handleBodyPart(bodyPart));
@@ -64,7 +63,7 @@ public class BatchResponseTransformator implements BatchTransformator {
if (bodyPart.isChangeSet()) {
for (BatchQueryOperation operation : bodyPart.getRequests()) {
- bodyPartResult.add(transformChangeSet((BatchChangeSet) operation));
+ bodyPartResult.add(transformChangeSet((BatchChangeSetPart) operation));
}
} else {
bodyPartResult.add(transformQueryOperation(bodyPart.getRequests().get(0), getContentId(bodyPart.getHeaders())));
@@ -73,7 +72,7 @@ public class BatchResponseTransformator implements BatchTransformator {
return bodyPartResult;
}
- private BatchSingleResponse transformChangeSet(final BatchChangeSet changeSet) throws BatchException {
+ private BatchSingleResponse transformChangeSet(final BatchChangeSetPart changeSet) throws BatchException {
BatchTransformatorCommon.validateContentTransferEncoding(changeSet.getHeaders(), true);
return transformQueryOperation(changeSet.getRequest(), getContentId(changeSet.getHeaders()));
@@ -84,8 +83,8 @@ public class BatchResponseTransformator implements BatchTransformator {
BatchSingleResponseImpl response = new BatchSingleResponseImpl();
response.setContentId(contentId);
response.setHeaders(BatchParserCommon.headerFieldMapToSingleMap(operation.getHeaders()));
- response.setStatusCode(getStatusCode(operation.httpMethod));
- response.setStatusInfo(getStatusInfo(operation.getHttpMethod()));
+ response.setStatusCode(getStatusCode(operation.httpStatusLine));
+ response.setStatusInfo(getStatusInfo(operation.getHttpStatusLine()));
response.setBody(getBody(operation));
return response;
@@ -105,8 +104,8 @@ public class BatchResponseTransformator implements BatchTransformator {
private String getBody(final BatchQueryOperation operation) throws BatchException {
int contentLength = BatchTransformatorCommon.getContentLength(operation.getHeaders());
- List<String> body = BatchParserCommon.trimStringListToLength(operation.getBody(), contentLength);
- return BatchParserCommon.stringListToString(body);
+
+ return BatchParserCommon.trimStringListToStringLength(operation.getBody(), contentLength);
}
private String getStatusCode(final String httpMethod) throws BatchException {
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/1f90b733/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchTransformatorCommon.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchTransformatorCommon.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchTransformatorCommon.java
index 2098708..c9c8e0f 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchTransformatorCommon.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchTransformatorCommon.java
@@ -12,20 +12,16 @@ import org.apache.olingo.odata2.core.batch.v2.BatchParserCommon.HeaderField;
public class BatchTransformatorCommon {
public static void validateContentType(final Map<String, HeaderField> headers) throws BatchException {
- if (headers.containsKey(HttpHeaders.CONTENT_TYPE.toLowerCase(Locale.ENGLISH))) {
- HeaderField contentTypeField = headers.get(HttpHeaders.CONTENT_TYPE.toLowerCase(Locale.ENGLISH));
-
+ final HeaderField contentTypeField = headers.get(HttpHeaders.CONTENT_TYPE.toLowerCase(Locale.ENGLISH));
+ if (contentTypeField != null) {
if (contentTypeField.getValues().size() == 1) {
- String contentType = contentTypeField.getValues().get(0);
-
- if (!(HttpContentType.APPLICATION_HTTP.equalsIgnoreCase(contentType)
- || contentType.contains(HttpContentType.MULTIPART_MIXED))) {
+ final String contentType = contentTypeField.getValues().get(0);
+ if (!BatchParserCommon.PATTERN_MULTIPART_BOUNDARY.matcher(contentType).matches()
+ && !BatchParserCommon.PATTERN_CONTENT_TYPE_APPLICATION_HTTP.matcher(contentType).matches()) {
throw new BatchException(BatchException.INVALID_CONTENT_TYPE.addContent(HttpContentType.MULTIPART_MIXED
+ " or " + HttpContentType.APPLICATION_HTTP));
}
- } else if (contentTypeField.getValues().size() == 0) {
- throw new BatchException(BatchException.MISSING_CONTENT_TYPE);
} else {
throw new BatchException(BatchException.INVALID_HEADER);
}
@@ -34,7 +30,8 @@ public class BatchTransformatorCommon {
}
}
- public static void validateContentTransferEncoding(final Map<String, HeaderField> headers, boolean isChangeRequest)
+ public static void validateContentTransferEncoding(final Map<String, HeaderField> headers,
+ final boolean isChangeRequest)
throws BatchException {
if (headers.containsKey(BatchHelper.HTTP_CONTENT_TRANSFER_ENCODING.toLowerCase(Locale.ENGLISH))) {
HeaderField encodingField = headers.get(BatchHelper.HTTP_CONTENT_TRANSFER_ENCODING.toLowerCase(Locale.ENGLISH));
@@ -57,11 +54,6 @@ public class BatchTransformatorCommon {
}
}
- public static void parsePartSyntax(final BatchBodyPart bodyPart) throws BatchException {
- int contentLength = BatchTransformatorCommon.getContentLength(bodyPart.getHeaders());
- bodyPart.parse(contentLength);
- }
-
public static int getContentLength(final Map<String, HeaderField> headers) throws BatchException {
if (headers.containsKey(HttpHeaders.CONTENT_LENGTH.toLowerCase(Locale.ENGLISH))) {
@@ -79,6 +71,6 @@ public class BatchTransformatorCommon {
}
}
- return Integer.MAX_VALUE;
+ return -1;
}
}
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/1f90b733/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/AcceptParserTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/AcceptParserTest.java b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/AcceptParserTest.java
index a3c0512..b7d7fac 100644
--- a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/AcceptParserTest.java
+++ b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/AcceptParserTest.java
@@ -31,8 +31,10 @@ public class AcceptParserTest {
@Test
public void testAcceptHeader() throws BatchException {
- List<String> acceptHeaders =
- AcceptParser.parseAcceptHeaders("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
+ AcceptParser parser = new AcceptParser();
+ parser.addAcceptHeaderValue("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
+ List<String> acceptHeaders = parser.parseAcceptHeaders();
+
assertNotNull(acceptHeaders);
assertEquals(4, acceptHeaders.size());
assertEquals("text/html", acceptHeaders.get(0));
@@ -43,48 +45,58 @@ public class AcceptParserTest {
@Test
public void testAcceptHeaderWithParameter() throws BatchException {
- List<String> acceptHeaders = AcceptParser.parseAcceptHeaders("application/json;odata=verbose;q=1.0, */*;q=0.1");
+ AcceptParser parser = new AcceptParser();
+ parser.addAcceptHeaderValue("application/json;odata=verbose;q=1.0, */*;q=0.1");
+ List<String> acceptHeaders = parser.parseAcceptHeaders();
+
assertNotNull(acceptHeaders);
assertEquals(2, acceptHeaders.size());
assertEquals("application/json;odata=verbose", acceptHeaders.get(0));
- ;
assertEquals("*/*", acceptHeaders.get(1));
}
@Test
public void testAcceptHeaderWithParameterAndLws() throws BatchException {
- List<String> acceptHeaders = AcceptParser.parseAcceptHeaders("application/json; odata=verbose;q=1.0, */*;q=0.1");
+ AcceptParser parser = new AcceptParser();
+ parser.addAcceptHeaderValue("application/json; odata=verbose;q=1.0, */*;q=0.1");
+ List<String> acceptHeaders = parser.parseAcceptHeaders();
+
assertNotNull(acceptHeaders);
assertEquals(2, acceptHeaders.size());
assertEquals("application/json; odata=verbose", acceptHeaders.get(0));
- ;
assertEquals("*/*", acceptHeaders.get(1));
}
@Test
public void testAcceptHeaderWithTabulator() throws BatchException {
- List<String> acceptHeaders = AcceptParser.parseAcceptHeaders("application/json;\todata=verbose;q=1.0, */*;q=0.1");
+ AcceptParser parser = new AcceptParser();
+ parser.addAcceptHeaderValue("application/json;\todata=verbose;q=1.0, */*;q=0.1");
+ List<String> acceptHeaders = parser.parseAcceptHeaders();
+
assertNotNull(acceptHeaders);
assertEquals(2, acceptHeaders.size());
assertEquals("application/json;" + TAB + "odata=verbose", acceptHeaders.get(0));
- ;
assertEquals("*/*", acceptHeaders.get(1));
}
@Test
public void testAcceptHeaderWithTwoParameters() throws BatchException {
- List<String> acceptHeaders =
- AcceptParser.parseAcceptHeaders("application/xml;another=test ; param=alskdf, */*;q=0.1");
+ AcceptParser parser = new AcceptParser();
+ parser.addAcceptHeaderValue("application/xml;another=test ; param=alskdf, */*;q=0.1");
+ List<String> acceptHeaders = parser.parseAcceptHeaders();
+
assertNotNull(acceptHeaders);
assertEquals(2, acceptHeaders.size());
assertEquals("application/xml;another=test ; param=alskdf", acceptHeaders.get(0));
- ;
assertEquals("*/*", acceptHeaders.get(1));
}
@Test
public void testAcceptHeader2() throws BatchException {
- List<String> acceptHeaders = AcceptParser.parseAcceptHeaders("text/html;level=1, application/*, */*;q=0.1");
+ AcceptParser parser = new AcceptParser();
+ parser.addAcceptHeaderValue("text/html;level=1, application/*, */*;q=0.1");
+ List<String> acceptHeaders = parser.parseAcceptHeaders();
+
assertNotNull(acceptHeaders);
assertEquals(3, acceptHeaders.size());
assertEquals("text/html;level=1", acceptHeaders.get(0));
@@ -94,7 +106,10 @@ public class AcceptParserTest {
@Test
public void testMoreSpecificMediaType() throws BatchException {
- List<String> acceptHeaders = AcceptParser.parseAcceptHeaders("application/*, application/xml");
+ AcceptParser parser = new AcceptParser();
+ parser.addAcceptHeaderValue("application/*, application/xml");
+ List<String> acceptHeaders = parser.parseAcceptHeaders();
+
assertNotNull(acceptHeaders);
assertEquals(2, acceptHeaders.size());
assertEquals("application/xml", acceptHeaders.get(0));
@@ -103,28 +118,40 @@ public class AcceptParserTest {
@Test
public void testQualityParameter() throws BatchException {
- List<String> acceptHeaders = AcceptParser.parseAcceptHeaders("application/*, */*; q=0.012");
+ AcceptParser parser = new AcceptParser();
+ parser.addAcceptHeaderValue("application/*, */*; q=0.012");
+ List<String> acceptHeaders = parser.parseAcceptHeaders();
+
assertNotNull(acceptHeaders);
}
@Test(expected = BatchException.class)
public void testInvalidAcceptHeader() throws BatchException {
- AcceptParser.parseAcceptHeaders("appi cation/*, */*;q=0.1");
+ AcceptParser parser = new AcceptParser();
+ parser.addAcceptHeaderValue("appi cation/*, */*;q=0.1");
+ parser.parseAcceptHeaders();
}
@Test(expected = BatchException.class)
public void testInvalidQualityParameter() throws BatchException {
- AcceptParser.parseAcceptHeaders("appication/*, */*;q=0,9");
+ AcceptParser parser = new AcceptParser();
+ parser.addAcceptHeaderValue("appication/*, */*;q=0,9");
+ parser.parseAcceptHeaders();
}
@Test(expected = BatchException.class)
public void testInvalidQualityParameter2() throws BatchException {
- AcceptParser.parseAcceptHeaders("appication/*, */*;q=1.0001");
+ AcceptParser parser = new AcceptParser();
+ parser.addAcceptHeaderValue("appication/*, */*;q=1.0001");
+ parser.parseAcceptHeaders();
}
@Test
public void testAcceptLanguages() throws BatchException {
- List<String> acceptLanguageHeaders = AcceptParser.parseAcceptableLanguages("en-US,en;q=0.7,en-UK;q=0.9");
+ AcceptParser parser = new AcceptParser();
+ parser.addAcceptLanguageHeaderValue("en-US,en;q=0.7,en-UK;q=0.9");
+ List<String> acceptLanguageHeaders = parser.parseAcceptableLanguages();
+
assertNotNull(acceptLanguageHeaders);
assertEquals(3, acceptLanguageHeaders.size());
assertEquals("en-US", acceptLanguageHeaders.get(0));
@@ -134,20 +161,28 @@ public class AcceptParserTest {
@Test
public void testAllAcceptLanguages() throws BatchException {
- List<String> acceptLanguageHeaders = AcceptParser.parseAcceptableLanguages("*");
+ AcceptParser parser = new AcceptParser();
+ parser.addAcceptLanguageHeaderValue("*");
+ List<String> acceptLanguageHeaders = parser.parseAcceptableLanguages();
+
assertNotNull(acceptLanguageHeaders);
assertEquals(1, acceptLanguageHeaders.size());
}
@Test
public void testLongAcceptLanguageValue() throws BatchException {
- List<String> acceptLanguageHeaders = AcceptParser.parseAcceptableLanguages("english");
+ AcceptParser parser = new AcceptParser();
+ parser.addAcceptLanguageHeaderValue("english");
+ List<String> acceptLanguageHeaders = parser.parseAcceptableLanguages();
+
assertNotNull(acceptLanguageHeaders);
assertEquals("english", acceptLanguageHeaders.get(0));
}
@Test(expected = BatchException.class)
public void testInvalidAcceptLanguageValue() throws BatchException {
- AcceptParser.parseAcceptableLanguages("en_US");
+ AcceptParser parser = new AcceptParser();
+ parser.addAcceptLanguageHeaderValue("en_US");
+ parser.parseAcceptableLanguages();
}
}
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/1f90b733/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchParserCommonTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchParserCommonTest.java b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchParserCommonTest.java
index c9e9a6b..8451c55 100644
--- a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchParserCommonTest.java
+++ b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchParserCommonTest.java
@@ -1,54 +1,170 @@
package org.apache.olingo.odata2.core.batch;
-import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.*;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import org.apache.olingo.odata2.api.batch.BatchException;
+import org.apache.olingo.odata2.api.commons.HttpHeaders;
import org.apache.olingo.odata2.core.batch.v2.BatchParserCommon;
+import org.apache.olingo.odata2.core.batch.v2.BatchParserCommon.HeaderField;
import org.junit.Test;
public class BatchParserCommonTest {
-
+
+ private static final String CRLF = "\r\n";
+
@Test
- public void testTrimList() {
- final List<String> list = Arrays.asList(new String[] { "123\r\n", "abc", "a\n", "\r", "123" });
- final List<String> trimedList = BatchParserCommon.trimStringListToLength(list, 7);
-
- assertEquals(2, trimedList.size());
- assertEquals("123\r\n", trimedList.get(0));
- assertEquals("ab", trimedList.get(1));
+ public void testMultipleHeader() throws BatchException {
+ String[] messageRaw = new String[] {
+ "Content-Id: 1" + CRLF,
+ "Content-Id: 2" + CRLF,
+ "content-type: Application/http" + CRLF,
+ "content-transfer-encoding: Binary" + CRLF
+ };
+ List<String> message = new ArrayList<String>();
+ message.addAll(Arrays.asList(messageRaw));
+
+
+ final Map<String, HeaderField> header = BatchParserCommon.consumeHeaders(message);
+ assertNotNull(header);
+
+ final HeaderField contentIdHeaders = header.get(BatchHelper.HTTP_CONTENT_ID.toLowerCase(Locale.ENGLISH));
+ assertNotNull(contentIdHeaders);
+ assertEquals(2, contentIdHeaders.getValues().size());
+ assertEquals("1", contentIdHeaders.getValues().get(0));
+ assertEquals("2", contentIdHeaders.getValues().get(1));
}
-
+
@Test
- public void testTrimListWithEmptyString() {
- final List<String> list = Arrays.asList(new String[] { "123\r\n", "", "abc", "a\n", "\r", "123" });
- final List<String> trimedList = BatchParserCommon.trimStringListToLength(list, 7);
-
- assertEquals(3, trimedList.size());
- assertEquals("123\r\n", trimedList.get(0));
- assertEquals("", trimedList.get(1));
- assertEquals("ab", trimedList.get(2));
+ public void testMultipleHeaderSameValue() throws BatchException {
+ String[] messageRaw = new String[] {
+ "Content-Id: 1" + CRLF,
+ "Content-Id: 1" + CRLF,
+ "content-type: Application/http" + CRLF,
+ "content-transfer-encoding: Binary" + CRLF
+ };
+ List<String> message = new ArrayList<String>();
+ message.addAll(Arrays.asList(messageRaw));
+
+
+ final Map<String, HeaderField> header = BatchParserCommon.consumeHeaders(message);
+ assertNotNull(header);
+
+ final HeaderField contentIdHeaders = header.get(BatchHelper.HTTP_CONTENT_ID.toLowerCase(Locale.ENGLISH));
+ assertNotNull(contentIdHeaders);
+ assertEquals(1, contentIdHeaders.getValues().size());
+ assertEquals("1", contentIdHeaders.getValues().get(0));
}
-
+
@Test
- public void testTrimListTryToReadMoreThanStringLength() {
- final List<String> list = Arrays.asList(new String[] { "abc\r\n", "123" });
- final List<String> trimedList = BatchParserCommon.trimStringListToLength(list, 100);
-
- assertEquals(2, trimedList.size());
- assertEquals("abc\r\n", trimedList.get(0));
- assertEquals("123", trimedList.get(1));
+ public void testHeaderSperatedByComma() throws BatchException {
+ String[] messageRaw = new String[] {
+ "Content-Id: 1" + CRLF,
+ "Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11" + CRLF,
+ "content-type: Application/http" + CRLF,
+ "content-transfer-encoding: Binary" + CRLF
+ };
+ List<String> message = new ArrayList<String>();
+ message.addAll(Arrays.asList(messageRaw));
+
+
+ final Map<String, HeaderField> header = BatchParserCommon.consumeHeaders(message);
+ assertNotNull(header);
+
+ final HeaderField upgradeHeader = header.get("upgrade");
+ assertNotNull(upgradeHeader);
+ assertEquals(4, upgradeHeader.getValues().size());
+ assertEquals("HTTP/2.0", upgradeHeader.getValues().get(0));
+ assertEquals("SHTTP/1.3", upgradeHeader.getValues().get(1));
+ assertEquals("IRC/6.9", upgradeHeader.getValues().get(2));
+ assertEquals("RTA/x11", upgradeHeader.getValues().get(3));
}
-
+
@Test
- public void testTrimListEmpty() {
- final List<String> list = Arrays.asList(new String[0]);
- final List<String> trimedList = BatchParserCommon.trimStringListToLength(list, 7);
-
- assertEquals(0, trimedList.size());
+ public void testMultipleAcceptHeader() throws BatchException {
+ String[] messageRaw = new String[] {
+ "Accept: application/atomsvc+xml;q=0.8, application/json;odata=verbose;q=0.5, */*;q=0.1" + CRLF,
+ "Accept: text/plain;q=0.3" + CRLF,
+ "Accept-Language:en-US,en;q=0.7,en-UK;q=0.9" + CRLF,
+ "content-type: Application/http" + CRLF,
+ "content-transfer-encoding: Binary" + CRLF
+ };
+ List<String> message = new ArrayList<String>();
+ message.addAll(Arrays.asList(messageRaw));
+
+
+ final Map<String, HeaderField> header = BatchParserCommon.consumeHeaders(message);
+ assertNotNull(header);
+
+ final HeaderField acceptHeader = header.get(HttpHeaders.ACCEPT.toLowerCase());
+ assertNotNull(acceptHeader);
+ assertEquals(4, acceptHeader.getValues().size());
}
-
+
+ @Test
+ public void testMultipleAcceptHeaderSameValue() throws BatchException {
+ String[] messageRaw = new String[] {
+ "Accept: application/atomsvc+xml;q=0.8, application/json;odata=verbose;q=0.5, */*;q=0.1" + CRLF,
+ "Accept: application/atomsvc+xml;q=0.8" + CRLF,
+ "Accept-Language:en-US,en;q=0.7,en-UK;q=0.9" + CRLF,
+ "content-type: Application/http" + CRLF,
+ "content-transfer-encoding: Binary" + CRLF
+ };
+ List<String> message = new ArrayList<String>();
+ message.addAll(Arrays.asList(messageRaw));
+
+
+ final Map<String, HeaderField> header = BatchParserCommon.consumeHeaders(message);
+ assertNotNull(header);
+
+ final HeaderField acceptHeader = header.get(HttpHeaders.ACCEPT.toLowerCase());
+ assertNotNull(acceptHeader);
+ assertEquals(3, acceptHeader.getValues().size());
+ }
+
+ @Test
+ public void testMultipleAccepLanguagetHeader() throws BatchException {
+ String[] messageRaw = new String[] {
+ "Accept-Language:en-US,en;q=0.7,en-UK;q=0.9" + CRLF,
+ "Accept-Language: de-DE;q=0.3" + CRLF,
+ "content-type: Application/http" + CRLF,
+ "content-transfer-encoding: Binary" + CRLF
+ };
+ List<String> message = new ArrayList<String>();
+ message.addAll(Arrays.asList(messageRaw));
+
+ final Map<String, HeaderField> header = BatchParserCommon.consumeHeaders(message);
+ assertNotNull(header);
+
+ final HeaderField acceptLanguageHeader = header.get(HttpHeaders.ACCEPT_LANGUAGE.toLowerCase());
+ assertNotNull(acceptLanguageHeader);
+ assertEquals(4, acceptLanguageHeader.getValues().size());
+ }
+
+ @Test
+ public void testMultipleAccepLanguagetHeaderSameValue() throws BatchException {
+ String[] messageRaw = new String[] {
+ "Accept-Language:en-US,en;q=0.7,en-UK;q=0.9" + CRLF,
+ "Accept-Language:en-US,en;q=0.7" + CRLF,
+ "content-type: Application/http" + CRLF,
+ "content-transfer-encoding: Binary" + CRLF
+ };
+ List<String> message = new ArrayList<String>();
+ message.addAll(Arrays.asList(messageRaw));
+
+ final Map<String, HeaderField> header = BatchParserCommon.consumeHeaders(message);
+ assertNotNull(header);
+
+ final HeaderField acceptLanguageHeader = header.get(HttpHeaders.ACCEPT_LANGUAGE.toLowerCase());
+ assertNotNull(acceptLanguageHeader);
+ assertEquals(3, acceptLanguageHeader.getValues().size());
+ }
+
@Test
public void testRemoveEndingCRLF() {
String line = "Test\r\n";
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/1f90b733/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestParserTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestParserTest.java b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestParserTest.java
index 7866004..4cd0b67 100644
--- a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestParserTest.java
+++ b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestParserTest.java
@@ -431,7 +431,7 @@ public class BatchRequestParserTest {
+ "--batch_8194-cf13-1f56--";
parseInvalidBatchBody(batch);
}
-
+
@Test(expected = BatchException.class)
public void testMissingContentTransferEncoding() throws BatchException {
String batch = "--batch_8194-cf13-1f56" + CRLF
@@ -439,7 +439,7 @@ public class BatchRequestParserTest {
+ CRLF
+ "--changeset_f980-1cb6-94dd" + CRLF
+ "Content-Type: application/http" + CRLF
- //+ "Content-Transfer-Encoding: binary" + CRLF
+ // + "Content-Transfer-Encoding: binary" + CRLF
+ CRLF
+ "POST Employees('2') HTTP/1.1" + CRLF
+ "Content-Type: application/json;odata=verbose" + CRLF
@@ -449,14 +449,14 @@ public class BatchRequestParserTest {
+ "--batch_8194-cf13-1f56--";
parseInvalidBatchBody(batch);
}
-
+
@Test(expected = BatchException.class)
public void testMissingContentType() throws BatchException {
String batch = "--batch_8194-cf13-1f56" + CRLF
+ "Content-Type: multipart/mixed;boundary=changeset_f980-1cb6-94dd" + CRLF
+ CRLF
+ "--changeset_f980-1cb6-94dd" + CRLF
- //+ "Content-Type: application/http" + CRLF
+ // + "Content-Type: application/http" + CRLF
+ "Content-Transfer-Encoding: binary" + CRLF
+ CRLF
+ "POST Employees('2') HTTP/1.1" + CRLF
@@ -467,7 +467,7 @@ public class BatchRequestParserTest {
+ "--batch_8194-cf13-1f56--";
parseInvalidBatchBody(batch);
}
-
+
@Test(expected = BatchException.class)
public void testNoCloseDelimiter() throws BatchException {
String batch = "--batch_8194-cf13-1f56" + CRLF
@@ -605,32 +605,33 @@ public class BatchRequestParserTest {
}
}
-
+
@SuppressWarnings("unused")
- @Test(expected=BatchException.class)
+ @Test(expected = BatchException.class)
+ @Ignore("This header should not be validated")
public void testNegativeContentLength() throws BatchException, IOException {
- String batch = ""
- + "--batch_8194-cf13-1f56" + CRLF
- + "Content-Type: multipart/mixed; boundary=changeset_f980-1cb6-94dd" + CRLF
- + "Content-Length: -2" + CRLF
- + CRLF
- + "--changeset_f980-1cb6-94dd" + CRLF
- + MIME_HEADERS
- + "Content-ID: " + PUT_MIME_HEADER_CONTENT_ID + CRLF
- + CRLF
- + "PUT $" + CONTENT_ID_REFERENCE + "/EmployeeName HTTP/1.1" + CRLF
- + "Content-Type: application/json;odata=verbose" + CRLF
- + "Content-Id:" + PUT_REQUEST_HEADER_CONTENT_ID + CRLF
- + CRLF
- + "{\"EmployeeName\":\"Peter Fall\"}" + CRLF
- + "--changeset_f980-1cb6-94dd--" + CRLF
- + CRLF
- + "--batch_8194-cf13-1f56--";
- InputStream in = new ByteArrayInputStream(batch.getBytes());
- BatchParser parser = new BatchParser(contentType, batchProperties, true);
- List<BatchRequestPart> batchRequestParts = parser.parseBatchRequest(in);
+ String batch = ""
+ + "--batch_8194-cf13-1f56" + CRLF
+ + "Content-Type: multipart/mixed; boundary=changeset_f980-1cb6-94dd" + CRLF
+ + "Content-Length: -2" + CRLF
+ + CRLF
+ + "--changeset_f980-1cb6-94dd" + CRLF
+ + MIME_HEADERS
+ + "Content-ID: " + PUT_MIME_HEADER_CONTENT_ID + CRLF
+ + CRLF
+ + "PUT $" + CONTENT_ID_REFERENCE + "/EmployeeName HTTP/1.1" + CRLF
+ + "Content-Type: application/json;odata=verbose" + CRLF
+ + "Content-Id:" + PUT_REQUEST_HEADER_CONTENT_ID + CRLF
+ + CRLF
+ + "{\"EmployeeName\":\"Peter Fall\"}" + CRLF
+ + "--changeset_f980-1cb6-94dd--" + CRLF
+ + CRLF
+ + "--batch_8194-cf13-1f56--";
+ InputStream in = new ByteArrayInputStream(batch.getBytes());
+ BatchParser parser = new BatchParser(contentType, batchProperties, true);
+ List<BatchRequestPart> batchRequestParts = parser.parseBatchRequest(in);
}
-
+
@SuppressWarnings("unused")
@Test
public void testNegativeContentLengthChangeSet() throws BatchException, IOException {
@@ -655,9 +656,9 @@ public class BatchRequestParserTest {
BatchParser parser = new BatchParser(contentType, batchProperties, true);
List<BatchRequestPart> batchRequestParts = parser.parseBatchRequest(in);
}
-
+
@SuppressWarnings("unused")
- @Test(expected=BatchException.class)
+ @Test(expected = BatchException.class)
public void testNegativeContentLengthRequest() throws BatchException, IOException {
String batch = ""
+ "--batch_8194-cf13-1f56" + CRLF
@@ -680,7 +681,7 @@ public class BatchRequestParserTest {
BatchParser parser = new BatchParser(contentType, batchProperties, true);
List<BatchRequestPart> batchRequestParts = parser.parseBatchRequest(in);
}
-
+
@Test
public void testContentLengthGreatherThanBodyLength() throws BatchException, IOException {
String batch = ""
@@ -746,6 +747,7 @@ public class BatchRequestParserTest {
}
@Test(expected = BatchException.class)
+ @Ignore("This header should not be validated")
public void testCutChangeSetDelimiter() throws BatchException, IOException {
String batch = ""
+ "--batch_8194-cf13-1f56" + CRLF
@@ -918,7 +920,7 @@ public class BatchRequestParserTest {
}
}
}
-
+
@Test
public void testNoContentId() throws BatchException {
String batch = "--batch_8194-cf13-1f56" + CRLF
@@ -950,10 +952,10 @@ public class BatchRequestParserTest {
+ "--batch_8194-cf13-1f56--";
InputStream in = new ByteArrayInputStream(batch.getBytes());
BatchParser parser = new BatchParser(contentType, batchProperties, true);
- List<BatchRequestPart> batchRequestParts = parser.parseBatchRequest(in); // No exception should be thrown
+ List<BatchRequestPart> batchRequestParts = parser.parseBatchRequest(in); // No exception should be thrown
assertNotNull(batchRequestParts);
}
-
+
@Test
public void testPreamble() throws BatchException, IOException {
String batch = ""
@@ -1017,6 +1019,60 @@ public class BatchRequestParserTest {
inputStreamToString(changeSetPart.getRequests().get(1).getBody()));
}
+ @SuppressWarnings("unused")
+ @Test
+ public void testContentTypeCaseInsensitive() throws BatchException, IOException {
+ String batch = ""
+ + "--batch_8194-cf13-1f56" + CRLF
+ + "Content-Type: muLTiParT/mixed; boundary=changeset_f980-1cb6-94dd" + CRLF
+ + CRLF
+ + "--changeset_f980-1cb6-94dd" + CRLF
+ + MIME_HEADERS
+ + "Content-ID: " + PUT_MIME_HEADER_CONTENT_ID + CRLF
+ + "Content-Length: -2" + CRLF
+ + CRLF
+ + "PUT $" + CONTENT_ID_REFERENCE + "/EmployeeName HTTP/1.1" + CRLF
+ + "Content-Type: application/json;odata=verbose" + CRLF
+ + "Content-Id:" + PUT_REQUEST_HEADER_CONTENT_ID + CRLF
+ + CRLF
+ + "{\"EmployeeName\":\"Peter Fall\"}" + CRLF
+ + "--changeset_f980-1cb6-94dd--" + CRLF
+ + CRLF
+ + "--batch_8194-cf13-1f56--";
+ InputStream in = new ByteArrayInputStream(batch.getBytes());
+ BatchParser parser = new BatchParser(contentType, batchProperties, true);
+ List<BatchRequestPart> batchRequestParts = parser.parseBatchRequest(in);
+ }
+
+ @Test
+ public void testContentTypeBoundaryCaseInsensitive() throws BatchException, IOException {
+ String batch = ""
+ + "--batch_8194-cf13-1f56" + CRLF
+ + "Content-Type: multipart/mixed; bOunDaRy=changeset_f980-1cb6-94dd" + CRLF
+ + CRLF
+ + "--changeset_f980-1cb6-94dd" + CRLF
+ + MIME_HEADERS
+ + "Content-ID: " + PUT_MIME_HEADER_CONTENT_ID + CRLF
+ + "Content-Length: -2" + CRLF
+ + CRLF
+ + "PUT $" + CONTENT_ID_REFERENCE + "/EmployeeName HTTP/1.1" + CRLF
+ + "Content-Type: application/json;odata=verbose" + CRLF
+ + "Content-Id:" + PUT_REQUEST_HEADER_CONTENT_ID + CRLF
+ + CRLF
+ + "{\"EmployeeName\":\"Peter Fall\"}" + CRLF
+ + "--changeset_f980-1cb6-94dd--" + CRLF
+ + CRLF
+ + "--batch_8194-cf13-1f56--";
+ InputStream in = new ByteArrayInputStream(batch.getBytes());
+ BatchParser parser = new BatchParser(contentType, batchProperties, true);
+ List<BatchRequestPart> batchRequestParts = parser.parseBatchRequest(in);
+
+ assertNotNull(batchRequestParts);
+ assertEquals(1, batchRequestParts.size());
+ assertTrue(batchRequestParts.get(0).isChangeSet());
+ assertEquals(1, batchRequestParts.get(0).getRequests().size());
+ }
+
@Test
public void testEpilog() throws BatchException, IOException {
String batch = ""
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/1f90b733/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchTransformatorCommonTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchTransformatorCommonTest.java b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchTransformatorCommonTest.java
index a0ab9f4..a70d15a 100644
--- a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchTransformatorCommonTest.java
+++ b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchTransformatorCommonTest.java
@@ -26,7 +26,17 @@ public class BatchTransformatorCommonTest {
@Test
public void testValidateContentTypeMultipartMixed() throws BatchException {
- List<String> contentTypeValues = Arrays.asList(new String[] { HttpContentType.MULTIPART_MIXED });
+ List<String> contentTypeValues =
+ Arrays.asList(new String[] { HttpContentType.MULTIPART_MIXED + "; boundary=batch_32332_32323_fdsf" });
+ Map<String, HeaderField> headers = makeHeaders(HttpHeaders.CONTENT_TYPE, contentTypeValues);
+
+ BatchTransformatorCommon.validateContentType(headers);
+ }
+
+ @Test
+ public void testValidateContentTypeMultipartMixedCaseInsensitiv() throws BatchException {
+ List<String> contentTypeValues =
+ Arrays.asList(new String[] { "mulTiPart/MiXed; boundary=batch_32332_32323_fdsf" });
Map<String, HeaderField> headers = makeHeaders(HttpHeaders.CONTENT_TYPE, contentTypeValues);
BatchTransformatorCommon.validateContentType(headers);
[4/4] git commit: Line number tracking and exception messages
Posted by ch...@apache.org.
Line number tracking and exception messages
Signed-off-by: Christian Amend <ch...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata2/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata2/commit/f0dc0f74
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata2/tree/f0dc0f74
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata2/diff/f0dc0f74
Branch: refs/heads/olingo436BatchRefactoring
Commit: f0dc0f74593a3184c84dbf43337b23ec52f57abb
Parents: 05d20c1
Author: Christian Holzer <c....@sap.com>
Authored: Mon Oct 6 13:01:40 2014 +0200
Committer: Christian Amend <ch...@apache.org>
Committed: Mon Oct 6 13:54:39 2014 +0200
----------------------------------------------------------------------
.../olingo/odata2/api/batch/BatchException.java | 2 +-
.../odata2/core/batch/v2/BatchBodyPart.java | 31 +-
.../core/batch/v2/BatchChangeSetPart.java | 7 +-
.../odata2/core/batch/v2/BatchParser.java | 11 +-
.../odata2/core/batch/v2/BatchParserCommon.java | 101 +-
.../core/batch/v2/BatchQueryOperation.java | 22 +-
.../batch/v2/BatchRequestTransformator.java | 74 +-
.../batch/v2/BatchResponseTransformator.java | 10 +-
.../core/batch/v2/BatchTransformatorCommon.java | 31 +-
.../v2/BufferedReaderIncludingLineEndings.java | 60 +-
.../olingo/odata2/core/batch/v2/Header.java | 142 +-
.../src/main/resources/i18n.properties | 37 +-
.../core/batch/BatchParserCommonTest.java | 55 +-
.../core/batch/BatchRequestParserTest.java | 82 +-
.../odata2/core/batch/BatchRequestTest.java | 5 +-
.../batch/BatchTransformatorCommonTest.java | 8 +-
.../BufferedReaderIncludingLineEndingsTest.java | 25 +-
.../olingo/odata2/core/batch/HeaderTest.java | 54 +-
.../src/test/resources/batchLarge.batch | 2505 ++++++++++++++++++
19 files changed, 2911 insertions(+), 351 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/f0dc0f74/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchException.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchException.java b/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchException.java
index 1171719..96aa4dd 100644
--- a/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchException.java
+++ b/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchException.java
@@ -94,7 +94,7 @@ public class BatchException extends ODataMessageException {
public static final MessageReference INVALID_ACCEPT_LANGUAGE_HEADER = createMessageReference(BatchException.class,
"INVALID_ACCEPT_LANGUAGE_HEADER");
- /** INVALID_CONTENT_TRANSFER_ENCODING requires no content value */
+ /** INVALID_CONTENT_TRANSFER_ENCODING requires 1 content value */
public static final MessageReference INVALID_CONTENT_TRANSFER_ENCODING = createMessageReference(BatchException.class,
"INVALID_CONTENT_TRANSFER_ENCODING");
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/f0dc0f74/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchBodyPart.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchBodyPart.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchBodyPart.java
index f74ea85..288ca1c 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchBodyPart.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchBodyPart.java
@@ -23,17 +23,19 @@ import java.util.List;
import org.apache.olingo.odata2.api.batch.BatchException;
import org.apache.olingo.odata2.api.commons.HttpHeaders;
+import org.apache.olingo.odata2.core.batch.v2.BufferedReaderIncludingLineEndings.Line;
+import org.apache.olingo.odata2.core.batch.v2.Header.HeaderField;
public class BatchBodyPart implements BatchPart {
final private String boundary;
final private boolean isStrict;
- final List<String> remainingMessage = new LinkedList<String>();
+ final List<Line> remainingMessage = new LinkedList<Line>();
private Header headers;
private boolean isChangeSet;
private List<BatchQueryOperation> requests;
- public BatchBodyPart(final List<String> bodyPartMessage, final String boundary, final boolean isStrict)
+ public BatchBodyPart(final List<Line> bodyPartMessage, final String boundary, final boolean isStrict)
throws BatchException {
this.boundary = boundary;
this.isStrict = isStrict;
@@ -55,7 +57,7 @@ public class BatchBodyPart implements BatchPart {
boolean isChangeSet = false;
if (contentTypes.size() == 0) {
- throw new BatchException(BatchException.MISSING_CONTENT_TYPE);
+ throw new BatchException(BatchException.MISSING_CONTENT_TYPE.addContent(headers.getLineNumber()));
}
for (String contentType : contentTypes) {
@@ -71,7 +73,7 @@ public class BatchBodyPart implements BatchPart {
return BatchParserCommon.PATTERN_MULTIPART_BOUNDARY.matcher(contentType).matches();
}
- private List<BatchQueryOperation> consumeRequest(final List<String> remainingMessage) throws BatchException {
+ private List<BatchQueryOperation> consumeRequest(final List<Line> remainingMessage) throws BatchException {
if (isChangeSet) {
return consumeChangeSet(remainingMessage);
} else {
@@ -79,28 +81,30 @@ public class BatchBodyPart implements BatchPart {
}
}
- private List<BatchQueryOperation> consumeChangeSet(final List<String> remainingMessage)
+ private List<BatchQueryOperation> consumeChangeSet(final List<Line> remainingMessage)
throws BatchException {
- final List<List<String>> changeRequests = splitChangeSet(remainingMessage);
+ final List<List<Line>> changeRequests = splitChangeSet(remainingMessage);
final List<BatchQueryOperation> requestList = new LinkedList<BatchQueryOperation>();
- for (List<String> changeRequest : changeRequests) {
+ for (List<Line> changeRequest : changeRequests) {
requestList.add(new BatchChangeSetPart(changeRequest, isStrict).parse());
}
return requestList;
}
- private List<List<String>> splitChangeSet(final List<String> remainingMessage)
+ private List<List<Line>> splitChangeSet(final List<Line> remainingMessage)
throws BatchException {
- final String changeSetBoundary = BatchParserCommon.getBoundary(headers.getHeaderNotNull(HttpHeaders.CONTENT_TYPE));
- validateChangeSetBoundary(changeSetBoundary);
+ final HeaderField contentTypeField = headers.getHeaderField(HttpHeaders.CONTENT_TYPE);
+ final String changeSetBoundary =
+ BatchParserCommon.getBoundary(contentTypeField.getValueNotNull(), contentTypeField.getLineNumber());
+ validateChangeSetBoundary(changeSetBoundary, headers);
return BatchParserCommon.splitMessageByBoundary(remainingMessage, changeSetBoundary);
}
- private List<BatchQueryOperation> consumeQueryOperation(final List<String> remainingMessage)
+ private List<BatchQueryOperation> consumeQueryOperation(final List<Line> remainingMessage)
throws BatchException {
final List<BatchQueryOperation> requestList = new LinkedList<BatchQueryOperation>();
requestList.add(new BatchQueryOperation(remainingMessage, isStrict).parse());
@@ -108,9 +112,10 @@ public class BatchBodyPart implements BatchPart {
return requestList;
}
- private void validateChangeSetBoundary(final String changeSetBoundary) throws BatchException {
+ private void validateChangeSetBoundary(final String changeSetBoundary, Header header) throws BatchException {
if (changeSetBoundary.equals(boundary)) {
- throw new BatchException(BatchException.INVALID_BOUNDARY);
+ throw new BatchException(BatchException.INVALID_BOUNDARY.addContent(header.getHeaderField(
+ HttpHeaders.CONTENT_TYPE).getLineNumber()));
}
}
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/f0dc0f74/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchChangeSetPart.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchChangeSetPart.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchChangeSetPart.java
index 746c368..f3b0699 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchChangeSetPart.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchChangeSetPart.java
@@ -21,11 +21,12 @@ package org.apache.olingo.odata2.core.batch.v2;
import java.util.List;
import org.apache.olingo.odata2.api.batch.BatchException;
+import org.apache.olingo.odata2.core.batch.v2.BufferedReaderIncludingLineEndings.Line;
public class BatchChangeSetPart extends BatchQueryOperation {
private BatchQueryOperation request;
- public BatchChangeSetPart(final List<String> message, final boolean isStrict) throws BatchException {
+ public BatchChangeSetPart(final List<Line> message, final boolean isStrict) throws BatchException {
super(message, isStrict);
}
@@ -44,12 +45,12 @@ public class BatchChangeSetPart extends BatchQueryOperation {
}
@Override
- public List<String> getBody() {
+ public List<Line> getBody() {
return request.getBody();
}
@Override
- public String getHttpStatusLine() {
+ public Line getHttpStatusLine() {
return request.getHttpStatusLine();
}
}
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/f0dc0f74/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchParser.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchParser.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchParser.java
index 6fb7dbd..00a1f2a 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchParser.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchParser.java
@@ -31,6 +31,7 @@ import org.apache.olingo.odata2.api.client.batch.BatchSingleResponse;
import org.apache.olingo.odata2.api.ep.EntityProviderBatchProperties;
import org.apache.olingo.odata2.api.uri.PathInfo;
import org.apache.olingo.odata2.api.uri.PathSegment;
+import org.apache.olingo.odata2.core.batch.v2.BufferedReaderIncludingLineEndings.Line;
import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
public class BatchParser {
@@ -78,11 +79,11 @@ public class BatchParser {
final BatchTransformator transformator) throws BatchException, IOException {
final String baseUri = getBaseUri();
- final String boundary = BatchParserCommon.getBoundary(contentTypeMime);
+ final String boundary = BatchParserCommon.getBoundary(contentTypeMime, 1);
final List<BatchParserResult> resultList = new LinkedList<BatchParserResult>();
- final List<List<String>> bodyPartStrings = splitBodyParts(in, boundary);
+ final List<List<Line>> bodyPartStrings = splitBodyParts(in, boundary);
- for (List<String> bodyPartString : bodyPartStrings) {
+ for (List<Line> bodyPartString : bodyPartStrings) {
BatchBodyPart bodyPart = new BatchBodyPart(bodyPartString, boundary, isStrict).parse();
resultList.addAll(transformator.transform(bodyPart, batchRequestPathInfo, baseUri));
}
@@ -90,11 +91,11 @@ public class BatchParser {
return resultList;
}
- private List<List<String>> splitBodyParts(final InputStream in, final String boundary)
+ private List<List<Line>> splitBodyParts(final InputStream in, final String boundary)
throws IOException, BatchException {
final BufferedReaderIncludingLineEndings reader = new BufferedReaderIncludingLineEndings(new InputStreamReader(in));
- final List<String> message = reader.toList();
+ final List<Line> message = reader.toList();
reader.close();
return BatchParserCommon.splitMessageByBoundary(message, boundary);
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/f0dc0f74/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchParserCommon.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchParserCommon.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchParserCommon.java
index df62994..b028759 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchParserCommon.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchParserCommon.java
@@ -40,6 +40,7 @@ import org.apache.olingo.odata2.api.uri.PathSegment;
import org.apache.olingo.odata2.core.ODataPathSegmentImpl;
import org.apache.olingo.odata2.core.PathInfoImpl;
import org.apache.olingo.odata2.core.batch.AcceptParser;
+import org.apache.olingo.odata2.core.batch.v2.BufferedReaderIncludingLineEndings.Line;
import org.apache.olingo.odata2.core.commons.Decoder;
public class BatchParserCommon {
@@ -55,53 +56,52 @@ public class BatchParserCommon {
public static final Pattern PATTERN_CONTENT_TYPE_APPLICATION_HTTP = Pattern.compile(REG_EX_APPLICATION_HTTP,
Pattern.CASE_INSENSITIVE);
- public static String trimStringListToStringLength(final List<String> list, final int length) {
+ public static String trimLineListToLength(final List<Line> list, final int length) {
final String message = stringListToString(list);
final int lastIndex = Math.min(length, message.length());
return (lastIndex > 0) ? message.substring(0, lastIndex) : "";
}
- public static String stringListToString(final List<String> list) {
+ public static String stringListToString(final List<Line> list) {
StringBuilder builder = new StringBuilder();
- for (String currentLine : list) {
- builder.append(currentLine);
+ for (Line currentLine : list) {
+ builder.append(currentLine.toString());
}
return builder.toString();
}
- public static InputStream convertMessageToInputStream(final List<String> messageList, final int contentLength)
+ public static InputStream convertMessageToInputStream(final List<Line> messageList, final int contentLength)
throws BatchException {
- final String message = trimStringListToStringLength(messageList, contentLength);
+ final String message = trimLineListToLength(messageList, contentLength);
return new ByteArrayInputStream(message.getBytes());
}
- public static InputStream convertMessageToInputStream(final List<String> messageList)
+ public static InputStream convertMessageToInputStream(final List<Line> messageList)
throws BatchException {
final String message = stringListToString(messageList);
return new ByteArrayInputStream(message.getBytes());
}
- // TODO Splitten von InputStream, sodass nur eine Iteration erfolgen muss
- static List<List<String>> splitMessageByBoundary(final List<String> message, final String boundary)
+ static List<List<Line>> splitMessageByBoundary(final List<Line> message, final String boundary)
throws BatchException {
- final List<List<String>> messageParts = new LinkedList<List<String>>();
- List<String> currentPart = new ArrayList<String>();
+ final List<List<Line>> messageParts = new LinkedList<List<Line>>();
+ List<Line> currentPart = new ArrayList<Line>();
boolean isEndReached = false;
- for (String currentLine : message) {
- if (currentLine.contains("--" + boundary + "--")) {
+ for (Line currentLine : message) {
+ if (currentLine.toString().contains("--" + boundary + "--")) {
removeEndingCRLFFromList(currentPart);
messageParts.add(currentPart);
isEndReached = true;
- } else if (currentLine.contains("--" + boundary)) {
+ } else if (currentLine.toString().contains("--" + boundary)) {
removeEndingCRLFFromList(currentPart);
messageParts.add(currentPart);
- currentPart = new LinkedList<String>();
+ currentPart = new LinkedList<Line>();
} else {
currentPart.add(currentLine);
}
@@ -111,52 +111,57 @@ public class BatchParserCommon {
}
}
+ final int lineNumer = (message.size() > 0) ? message.get(0).getLineNumber() : 0;
// Remove preamble
if (messageParts.size() > 0) {
messageParts.remove(0);
} else {
- throw new BatchException(BatchException.MISSING_BOUNDARY_DELIMITER);
- }
- if (messageParts.size() == 0) {
- throw new BatchException(BatchException.NO_MATCH_WITH_BOUNDARY_STRING);
+ throw new BatchException(BatchException.MISSING_BOUNDARY_DELIMITER.addContent(lineNumer));
}
if (!isEndReached) {
- throw new BatchException(BatchException.MISSING_CLOSE_DELIMITER);
+ throw new BatchException(BatchException.MISSING_CLOSE_DELIMITER.addContent(lineNumer));
+ }
+
+ if (messageParts.size() == 0) {
+ throw new BatchException(BatchException.NO_MATCH_WITH_BOUNDARY_STRING.addContent(boundary).addContent(lineNumer));
}
return messageParts;
}
- private static void removeEndingCRLFFromList(final List<String> list) {
+ private static void removeEndingCRLFFromList(final List<Line> list) {
if (list.size() > 0) {
- String lastLine = list.remove(list.size() - 1);
+ Line lastLine = list.remove(list.size() - 1);
list.add(removeEndingCRLF(lastLine));
}
}
- public static String removeEndingCRLF(final String line) {
+ public static Line removeEndingCRLF(final Line line) {
Pattern pattern = Pattern.compile("(.*)(\r\n){1}( *)", Pattern.DOTALL);
- Matcher matcher = pattern.matcher(line);
+ Matcher matcher = pattern.matcher(line.toString());
if (matcher.matches()) {
- return matcher.group(1);
+ return new Line(matcher.group(1), line.getLineNumber());
} else {
return line;
}
}
- public static Header consumeHeaders(final List<String> remainingMessage) throws BatchException {
- final Header headers = new Header();
+ public static Header consumeHeaders(final List<Line> remainingMessage) throws BatchException {
+ final int lineNumberOfHeader = remainingMessage.size() != 0 ? remainingMessage.get(0).getLineNumber() : 0;
+ final Header headers = new Header(lineNumberOfHeader);
boolean isHeader = true;
- final Iterator<String> iter = remainingMessage.iterator();
+ final Iterator<Line> iter = remainingMessage.iterator();
final AcceptParser acceptParser = new AcceptParser();
- String currentLine;
+ Line currentLine;
+ int acceptLineNumber = 0;
+ int acceptLanguageLineNumber = 0;
while (iter.hasNext() && isHeader) {
currentLine = iter.next();
- final Matcher headerMatcher = PATTERN_HEADER_LINE.matcher(currentLine);
+ final Matcher headerMatcher = PATTERN_HEADER_LINE.matcher(currentLine.toString());
if (headerMatcher.matches() && headerMatcher.groupCount() == 2) {
iter.remove();
@@ -166,34 +171,37 @@ public class BatchParserCommon {
if (HttpHeaders.ACCEPT.equalsIgnoreCase(headerName)) {
acceptParser.addAcceptHeaderValue(headerValue);
+ acceptLineNumber = currentLine.getLineNumber();
} else if (HttpHeaders.ACCEPT_LANGUAGE.equalsIgnoreCase(headerName)) {
acceptParser.addAcceptLanguageHeaderValue(headerValue);
+ acceptLanguageLineNumber = currentLine.getLineNumber();
} else {
- headers.addHeader(headerName, Header.splitValuesByComma(headerValue));
+ headers.addHeader(headerName, Header.splitValuesByComma(headerValue), currentLine.getLineNumber());
}
} else {
isHeader = false;
}
}
- headers.addHeader(HttpHeaders.ACCEPT, acceptParser.parseAcceptHeaders());
- headers.addHeader(HttpHeaders.ACCEPT_LANGUAGE, acceptParser.parseAcceptableLanguages());
+ headers.addHeader(HttpHeaders.ACCEPT, acceptParser.parseAcceptHeaders(), acceptLineNumber);
+ headers.addHeader(HttpHeaders.ACCEPT_LANGUAGE, acceptParser.parseAcceptableLanguages(), acceptLanguageLineNumber);
return headers;
}
- public static void consumeBlankLine(final List<String> remainingMessage, final boolean isStrict)
+ public static void consumeBlankLine(final List<Line> remainingMessage, final boolean isStrict)
throws BatchException {
- if (remainingMessage.size() > 0 && "".equals(remainingMessage.get(0).trim())) {
+ if (remainingMessage.size() > 0 && "".equals(remainingMessage.get(0).toString().trim())) {
remainingMessage.remove(0);
} else {
if (isStrict) {
- throw new BatchException(BatchException.MISSING_BLANK_LINE);
+ final int lineNumber = (remainingMessage.size() > 0) ? remainingMessage.get(0).getLineNumber() : 0;
+ throw new BatchException(BatchException.MISSING_BLANK_LINE.addContent("[None]").addContent(lineNumber));
}
}
}
- public static String getBoundary(final String contentType) throws BatchException {
+ public static String getBoundary(final String contentType, final int line) throws BatchException {
final Matcher boundaryMatcher = PATTERN_MULTIPART_BOUNDARY.matcher(contentType);
if (boundaryMatcher.matches()) {
@@ -201,17 +209,17 @@ public class BatchParserCommon {
if (boundary.matches(REG_EX_BOUNDARY)) {
return trimQuota(boundary);
} else {
- throw new BatchException(BatchException.INVALID_BOUNDARY);
+ throw new BatchException(BatchException.INVALID_BOUNDARY.addContent(line));
}
} else {
throw new BatchException(BatchException.INVALID_CONTENT_TYPE.addContent(HttpContentType.MULTIPART_MIXED));
}
}
- public static Map<String, List<String>> parseQueryParameter(final String httpRequest) {
+ public static Map<String, List<String>> parseQueryParameter(final Line httpRequest) {
Map<String, List<String>> queryParameter = new HashMap<String, List<String>>();
- String[] requestParts = httpRequest.split(" ");
+ String[] requestParts = httpRequest.toString().split(" ");
if (requestParts.length == 3) {
String[] parts = requestParts[1].split("\\?");
@@ -239,8 +247,8 @@ public class BatchParserCommon {
return queryParameter;
}
- public static PathInfo parseRequestUri(final String httpRequest, final PathInfo batchRequestPathInfo,
- final String baseUri)
+ public static PathInfo parseRequestUri(final Line httpStatusLine, final PathInfo batchRequestPathInfo,
+ final String baseUri, final int line)
throws BatchException {
final String odataPathSegmentsAsString;
@@ -250,7 +258,7 @@ public class BatchParserCommon {
pathInfo.setServiceRoot(batchRequestPathInfo.getServiceRoot());
pathInfo.setPrecedingPathSegment(batchRequestPathInfo.getPrecedingSegments());
- String[] requestParts = httpRequest.split(" ");
+ String[] requestParts = httpStatusLine.toString().split(" ");
if (requestParts.length == 3) {
String uri = requestParts[1];
Pattern regexRequestUri;
@@ -277,14 +285,15 @@ public class BatchParserCommon {
}
} else {
- throw new BatchException(BatchException.INVALID_URI);
+ throw new BatchException(BatchException.INVALID_URI.addContent(httpStatusLine.getLineNumber()));
}
} catch (URISyntaxException e) {
- throw new BatchException(BatchException.INVALID_URI, e);
+ throw new BatchException(BatchException.INVALID_URI.addContent(line), e);
}
} else {
- throw new BatchException(BatchException.INVALID_REQUEST_LINE);
+ throw new BatchException(BatchException.INVALID_REQUEST_LINE.addContent(httpStatusLine.toString())
+ .addContent(line));
}
return pathInfo;
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/f0dc0f74/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchQueryOperation.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchQueryOperation.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchQueryOperation.java
index 87dcb23..9bbd019 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchQueryOperation.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchQueryOperation.java
@@ -21,17 +21,18 @@ package org.apache.olingo.odata2.core.batch.v2;
import java.util.List;
import org.apache.olingo.odata2.api.batch.BatchException;
+import org.apache.olingo.odata2.core.batch.v2.BufferedReaderIncludingLineEndings.Line;
public class BatchQueryOperation implements BatchPart {
protected final boolean isStrict;
- protected String httpStatusLine;
+ protected Line httpStatusLine;
protected Header headers;
- protected List<String> body;
+ protected List<Line> body;
protected int bodySize;
- protected List<String> message;
+ protected List<Line> message;
- public BatchQueryOperation(final List<String> message, final boolean isStrict) {
+ public BatchQueryOperation(final List<Line> message, final boolean isStrict) {
this.isStrict = isStrict;
this.message = message;
}
@@ -45,22 +46,23 @@ public class BatchQueryOperation implements BatchPart {
return this;
}
- protected String consumeHttpStatusLine(final List<String> message) throws BatchException {
- if (message.size() > 0 && !message.get(0).trim().equals("")) {
- String method = message.get(0);
+ protected Line consumeHttpStatusLine(final List<Line> message) throws BatchException {
+ if (message.size() > 0 && !message.get(0).toString().trim().equals("")) {
+ final Line method = message.get(0);
message.remove(0);
return method;
} else {
- throw new BatchException(BatchException.INVALID_QUERY_OPERATION_METHOD);
+ final int line = (message.size() > 0) ? message.get(0).getLineNumber() : 0;
+ throw new BatchException(BatchException.MISSING_METHOD.addContent(line));
}
}
- public String getHttpStatusLine() {
+ public Line getHttpStatusLine() {
return httpStatusLine;
}
- public List<String> getBody() {
+ public List<Line> getBody() {
return body;
}
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/f0dc0f74/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchRequestTransformator.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchRequestTransformator.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchRequestTransformator.java
index a49a2e5..c7ffa88 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchRequestTransformator.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchRequestTransformator.java
@@ -32,12 +32,13 @@ import org.apache.olingo.odata2.api.batch.BatchException;
import org.apache.olingo.odata2.api.batch.BatchParserResult;
import org.apache.olingo.odata2.api.commons.HttpHeaders;
import org.apache.olingo.odata2.api.commons.ODataHttpMethod;
-import org.apache.olingo.odata2.api.exception.MessageReference;
import org.apache.olingo.odata2.api.processor.ODataRequest;
import org.apache.olingo.odata2.api.processor.ODataRequest.ODataRequestBuilder;
import org.apache.olingo.odata2.api.uri.PathInfo;
import org.apache.olingo.odata2.core.batch.BatchHelper;
import org.apache.olingo.odata2.core.batch.BatchRequestPartImpl;
+import org.apache.olingo.odata2.core.batch.v2.BufferedReaderIncludingLineEndings.Line;
+import org.apache.olingo.odata2.core.batch.v2.Header.HeaderField;
public class BatchRequestTransformator implements BatchTransformator {
@@ -88,9 +89,10 @@ public class BatchRequestTransformator implements BatchTransformator {
private ODataRequest createRequest(final BatchQueryOperation operation, final Header headers,
final PathInfo pathInfo, final String baseUri, final boolean isChangeSet) throws BatchException {
+ final int httpLineNumber = operation.getHttpStatusLine().getLineNumber();
ODataHttpMethod httpMethod = getHttpMethod(operation.getHttpStatusLine());
- validateHttpMethod(httpMethod, isChangeSet);
- validateBody(httpMethod, operation);
+ validateHttpMethod(httpMethod, isChangeSet, httpLineNumber);
+ validateBody(httpMethod, operation, httpLineNumber);
InputStream bodyStrean = getBodyStream(operation, headers, httpMethod);
ODataRequestBuilder requestBuilder = ODataRequest.method(httpMethod)
@@ -99,27 +101,26 @@ public class BatchRequestTransformator implements BatchTransformator {
.allQueryParameters(BatchParserCommon.parseQueryParameter(operation.getHttpStatusLine()))
.body(bodyStrean)
.requestHeaders(headers.toMultiMap())
- .pathInfo(BatchParserCommon.parseRequestUri(operation.getHttpStatusLine(), pathInfo, baseUri));
-
- final String contentType =headers.getHeader(HttpHeaders.CONTENT_TYPE);
- if(contentType != null) {
+ .pathInfo(BatchParserCommon.parseRequestUri(operation.getHttpStatusLine(), pathInfo, baseUri, 0));
+
+ final String contentType = headers.getHeader(HttpHeaders.CONTENT_TYPE);
+ if (contentType != null) {
requestBuilder.contentType(contentType);
}
-
-
+
return requestBuilder.build();
}
- private void validateBody(final ODataHttpMethod httpMethod, final BatchQueryOperation operation)
+ private void validateBody(final ODataHttpMethod httpStatusLine, final BatchQueryOperation operation, final int line)
throws BatchException {
- if (HTTP_BATCH_METHODS.contains(httpMethod.toString()) && isUnvalidGetRequestBody(operation)) {
- throw new BatchException(BatchException.INVALID_REQUEST_LINE);
+ if (HTTP_BATCH_METHODS.contains(httpStatusLine.toString()) && isUnvalidGetRequestBody(operation)) {
+ throw new BatchException(BatchException.INVALID_REQUEST_LINE.addContent(httpStatusLine).addContent(line));
}
}
private boolean isUnvalidGetRequestBody(final BatchQueryOperation operation) {
return (operation.getBody().size() > 1)
- || (operation.getBody().size() == 1 && !operation.getBody().get(0).trim().equals(""));
+ || (operation.getBody().size() == 1 && !operation.getBody().get(0).toString().trim().equals(""));
}
private InputStream getBodyStream(final BatchQueryOperation operation, Header headers,
@@ -140,28 +141,32 @@ public class BatchRequestTransformator implements BatchTransformator {
private Header transformHeader(final BatchPart operation, final BatchPart parentPart) {
final Header headers = operation.getHeaders().clone();
- headers.removeHeaders(BatchHelper.HTTP_CONTENT_ID);
- final List<String> operationContentIds = operation.getHeaders().getHeaders(BatchHelper.HTTP_CONTENT_ID);
- final List<String> parentContentIds = parentPart.getHeaders().getHeaders(BatchHelper.HTTP_CONTENT_ID);
+ headers.removeHeader(BatchHelper.HTTP_CONTENT_ID);
+ final HeaderField operationHeader = operation.getHeaders().getHeaderField(BatchHelper.HTTP_CONTENT_ID);
+ final HeaderField parentHeader = parentPart.getHeaders().getHeaderField(BatchHelper.HTTP_CONTENT_ID);
- if (operationContentIds.size() != 0) {
- headers.addHeader(BatchHelper.REQUEST_HEADER_CONTENT_ID, operationContentIds);
+ if (operationHeader != null && operationHeader.getValues().size() != 0) {
+ headers.addHeader(BatchHelper.REQUEST_HEADER_CONTENT_ID, operationHeader.getValues(), operationHeader
+ .getLineNumber());
}
- if (parentContentIds.size() != 0) {
- headers.addHeader(BatchHelper.MIME_HEADER_CONTENT_ID, parentContentIds);
+ if (parentHeader != null && parentHeader.getValues().size() != 0) {
+ headers.addHeader(BatchHelper.MIME_HEADER_CONTENT_ID, parentHeader.getValues(), parentHeader.getLineNumber());
}
return headers;
}
- private void validateHttpMethod(final ODataHttpMethod httpMethod, final boolean isChangeSet) throws BatchException {
+ private void validateHttpMethod(final ODataHttpMethod httpMethod, final boolean isChangeSet, final int line)
+ throws BatchException {
Set<String> validMethods = (isChangeSet) ? HTTP_CHANGE_SET_METHODS : HTTP_BATCH_METHODS;
if (!validMethods.contains(httpMethod.toString())) {
- MessageReference message =
- (isChangeSet) ? BatchException.INVALID_CHANGESET_METHOD : BatchException.INVALID_QUERY_OPERATION_METHOD;
- throw new BatchException(message);
+ if (isChangeSet) {
+ throw new BatchException(BatchException.INVALID_CHANGESET_METHOD.addContent(line));
+ } else {
+ throw new BatchException(BatchException.INVALID_QUERY_OPERATION_METHOD.addContent(line));
+ }
}
}
@@ -183,23 +188,20 @@ public class BatchRequestTransformator implements BatchTransformator {
return acceptLanguages;
}
- private ODataHttpMethod getHttpMethod(final String httpRequest) throws BatchException {
+ private ODataHttpMethod getHttpMethod(final Line httpRequest) throws BatchException {
ODataHttpMethod result = null;
- if (httpRequest != null) {
- String[] parts = httpRequest.split(" ");
+ String[] parts = httpRequest.toString().split(" ");
- if (parts.length == 3) {
- try {
- result = ODataHttpMethod.valueOf(parts[0]);
- } catch (IllegalArgumentException e) {
- throw new BatchException(BatchException.MISSING_METHOD, e);
- }
- } else {
- throw new BatchException(BatchException.INVALID_REQUEST_LINE);
+ if (parts.length == 3) {
+ try {
+ result = ODataHttpMethod.valueOf(parts[0]);
+ } catch (IllegalArgumentException e) {
+ throw new BatchException(BatchException.MISSING_METHOD.addContent(httpRequest.getLineNumber()), e);
}
} else {
- throw new BatchException(BatchException.INVALID_REQUEST_LINE);
+ throw new BatchException(BatchException.INVALID_REQUEST_LINE.addContent(httpRequest.toString()).addContent(
+ httpRequest.getLineNumber()));
}
return result;
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/f0dc0f74/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchResponseTransformator.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchResponseTransformator.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchResponseTransformator.java
index ab983ac..e800673 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchResponseTransformator.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchResponseTransformator.java
@@ -29,6 +29,7 @@ import org.apache.olingo.odata2.api.client.batch.BatchSingleResponse;
import org.apache.olingo.odata2.api.uri.PathInfo;
import org.apache.olingo.odata2.core.batch.BatchHelper;
import org.apache.olingo.odata2.core.batch.BatchSingleResponseImpl;
+import org.apache.olingo.odata2.core.batch.v2.BufferedReaderIncludingLineEndings.Line;
public class BatchResponseTransformator implements BatchTransformator {
@@ -92,14 +93,15 @@ public class BatchResponseTransformator implements BatchTransformator {
return response;
}
- private Matcher prepareStatusLineMatcher(String httpStatusLine) throws BatchException {
+ private Matcher prepareStatusLineMatcher(final Line httpStatusLine) throws BatchException {
final Pattern regexPattern = Pattern.compile(REG_EX_STATUS_LINE);
- final Matcher matcher = regexPattern.matcher(httpStatusLine);
+ final Matcher matcher = regexPattern.matcher(httpStatusLine.toString());
if (matcher.find()) {
return matcher;
} else {
- throw new BatchException(BatchException.INVALID_STATUS_LINE);
+ throw new BatchException(BatchException.INVALID_STATUS_LINE.addContent(httpStatusLine.toString())
+ .addContent(httpStatusLine.getLineNumber()));
}
}
@@ -109,7 +111,7 @@ public class BatchResponseTransformator implements BatchTransformator {
if (contentLength == -1) {
return BatchParserCommon.stringListToString(operation.getBody());
} else {
- return BatchParserCommon.trimStringListToStringLength(operation.getBody(), contentLength);
+ return BatchParserCommon.trimLineListToLength(operation.getBody(), contentLength);
}
}
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/f0dc0f74/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchTransformatorCommon.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchTransformatorCommon.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchTransformatorCommon.java
index 9c67f49..498dd2d 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchTransformatorCommon.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchTransformatorCommon.java
@@ -6,6 +6,7 @@ import org.apache.olingo.odata2.api.batch.BatchException;
import org.apache.olingo.odata2.api.commons.HttpContentType;
import org.apache.olingo.odata2.api.commons.HttpHeaders;
import org.apache.olingo.odata2.core.batch.BatchHelper;
+import org.apache.olingo.odata2.core.batch.v2.Header.HeaderField;
public class BatchTransformatorCommon {
@@ -24,39 +25,45 @@ public class BatchTransformatorCommon {
public static void validateContentTransferEncoding(final Header headers, final boolean isChangeRequest)
throws BatchException {
- final List<String> contentTransferEncodings = headers.getHeaders(BatchHelper.HTTP_CONTENT_TRANSFER_ENCODING);
+ final HeaderField contentTransferField = headers.getHeaderField(BatchHelper.HTTP_CONTENT_TRANSFER_ENCODING);
- if (contentTransferEncodings.size() != 0) {
- if (contentTransferEncodings.size() == 1) {
- String encoding = contentTransferEncodings.get(0);
+ if (contentTransferField != null) {
+ final List<String> contentTransferValues = contentTransferField.getValues();
+ if (contentTransferValues.size() == 1) {
+ String encoding = contentTransferValues.get(0);
if (!BatchHelper.BINARY_ENCODING.equalsIgnoreCase(encoding)) {
- throw new BatchException(BatchException.INVALID_CONTENT_TRANSFER_ENCODING);
+ throw new BatchException(
+ BatchException.INVALID_CONTENT_TRANSFER_ENCODING.addContent(contentTransferField.getLineNumber()));
}
} else {
- throw new BatchException(BatchException.INVALID_HEADER);
+ throw new BatchException(BatchException.INVALID_HEADER.addContent(contentTransferField.getLineNumber()));
}
} else {
if (isChangeRequest) {
- throw new BatchException(BatchException.INVALID_CONTENT_TRANSFER_ENCODING);
+ throw new BatchException(BatchException.INVALID_CONTENT_TRANSFER_ENCODING.addContent(headers.getLineNumber()));
}
}
}
public static int getContentLength(final Header headers) throws BatchException {
- final List<String> contentLengths = headers.getHeaders(HttpHeaders.CONTENT_LENGTH);
+ final HeaderField contentLengthField = headers.getHeaderField(HttpHeaders.CONTENT_LENGTH);
+
+ if (contentLengthField != null && contentLengthField.getValues().size() == 1) {
+ final List<String> contentLengthValues = contentLengthField.getValues();
- if (contentLengths.size() == 1) {
try {
- int contentLength = Integer.parseInt(contentLengths.get(0));
+ int contentLength = Integer.parseInt(contentLengthValues.get(0));
if (contentLength < 0) {
- throw new BatchException(BatchException.INVALID_HEADER);
+ throw new BatchException(BatchException.INVALID_HEADER.addContent(contentLengthField.getValue()).addContent(
+ contentLengthField.getLineNumber()));
}
return contentLength;
} catch (NumberFormatException e) {
- throw new BatchException(BatchException.INVALID_HEADER, e);
+ throw new BatchException(BatchException.INVALID_HEADER.addContent(contentLengthField.getValue()).addContent(
+ contentLengthField.getLineNumber()), e);
}
}
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/f0dc0f74/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BufferedReaderIncludingLineEndings.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BufferedReaderIncludingLineEndings.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BufferedReaderIncludingLineEndings.java
index 5e411ff..295f4c6 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BufferedReaderIncludingLineEndings.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BufferedReaderIncludingLineEndings.java
@@ -92,12 +92,13 @@ public class BufferedReaderIncludingLineEndings extends Reader {
return bytesRead;
}
- public List<String> toList() throws IOException {
- final List<String> result = new ArrayList<String>();
+ public List<Line> toList() throws IOException {
+ final List<Line> result = new ArrayList<Line>();
String currentLine;
+ int counter = 1;
while ((currentLine = readLine()) != null) {
- result.add(currentLine);
+ result.add(new Line(currentLine, counter++));
}
return result;
@@ -217,4 +218,57 @@ public class BufferedReaderIncludingLineEndings extends Reader {
return limit;
}
+
+ public static class Line {
+ private final int lineNumber;
+ private final String content;
+
+ public Line(final String content, final int lineNumber) {
+ this.content = content;
+ this.lineNumber = lineNumber;
+ }
+
+ public int getLineNumber() {
+ return lineNumber;
+ }
+
+ @Override
+ public String toString() {
+ return content;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((content == null) ? 0 : content.hashCode());
+ result = prime * result + lineNumber;
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ Line other = (Line) obj;
+ if (content == null) {
+ if (other.content != null) {
+ return false;
+ }
+ } else if (!content.equals(other.content)) {
+ return false;
+ }
+ if (lineNumber != other.lineNumber) {
+ return false;
+ }
+ return true;
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/f0dc0f74/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/Header.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/Header.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/Header.java
index 7901b7b..c9daa6a 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/Header.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/Header.java
@@ -10,20 +10,14 @@ import java.util.regex.Pattern;
public class Header implements Cloneable {
private final Map<String, HeaderField> headers = new HashMap<String, HeaderField>();
+ private int lineNumber;
- public static List<String> splitValuesByComma(final String headerValue) {
- final List<String> singleValues = new ArrayList<String>();
-
- String[] parts = headerValue.split(",");
- for (final String value : parts) {
- singleValues.add(value.trim());
- }
-
- return singleValues;
+ public Header(int lineNumer) {
+ this.lineNumber = lineNumer;
}
- public void addHeader(final String name, final String value) {
- final HeaderField headerField = getHeaderFieldOrDefault(name);
+ public void addHeader(final String name, final String value, final int lineNumber) {
+ final HeaderField headerField = getHeaderFieldOrDefault(name, lineNumber);
final List<String> headerValues = headerField.getValues();
if (!headerValues.contains(value)) {
@@ -31,8 +25,8 @@ public class Header implements Cloneable {
}
}
- public void addHeader(final String name, final List<String> values) {
- final HeaderField headerField = getHeaderFieldOrDefault(name);
+ public void addHeader(final String name, final List<String> values, final int lineNumber) {
+ final HeaderField headerField = getHeaderFieldOrDefault(name, lineNumber);
final List<String> headerValues = headerField.getValues();
for (final String value : values) {
@@ -41,45 +35,29 @@ public class Header implements Cloneable {
}
}
}
-
+
public boolean isHeaderMatching(final String name, final Pattern pattern) {
- if(getHeaders(name).size() != 1 ) {
+ if (getHeaders(name).size() != 1) {
return false;
} else {
return pattern.matcher(getHeaders(name).get(0)).matches();
}
}
-
- public void removeHeaders(final String name) {
+
+ public void removeHeader(final String name) {
headers.remove(name.toLowerCase(Locale.ENGLISH));
}
public String getHeader(final String name) {
final HeaderField headerField = getHeaderField(name);
-
- if (headerField == null) {
- return null;
- } else {
- final List<String> headerValues = headerField.getValues();
- final StringBuilder result = new StringBuilder();
-
- for (final String value : headerValues) {
- result.append(value);
- result.append(", ");
- }
-
- if(result.length()>0) {
- result.delete(result.length() - 2, result.length());
- }
-
- return result.toString();
- }
+
+ return (headerField == null) ? null : headerField.getValue();
}
public String getHeaderNotNull(final String name) {
- final String value = getHeader(name);
-
- return (value == null) ? "" : value;
+ final HeaderField headerField = getHeaderField(name);
+
+ return (headerField == null) ? "" : headerField.getValueNotNull();
}
public List<String> getHeaders(final String name) {
@@ -91,7 +69,11 @@ public class Header implements Cloneable {
public HeaderField getHeaderField(final String name) {
return headers.get(name.toLowerCase(Locale.ENGLISH));
}
-
+
+ public int getLineNumber() {
+ return lineNumber;
+ }
+
public Map<String, String> toSingleMap() {
final Map<String, String> singleMap = new HashMap<String, String>();
@@ -114,11 +96,11 @@ public class Header implements Cloneable {
return singleMap;
}
- private HeaderField getHeaderFieldOrDefault(final String name) {
+ private HeaderField getHeaderFieldOrDefault(final String name, final int lineNumber) {
HeaderField headerField = headers.get(name.toLowerCase(Locale.ENGLISH));
if (headerField == null) {
- headerField = new HeaderField(name);
+ headerField = new HeaderField(name, lineNumber);
headers.put(name.toLowerCase(Locale.ENGLISH), headerField);
}
@@ -127,7 +109,7 @@ public class Header implements Cloneable {
@Override
public Header clone() {
- final Header newInstance = new Header();
+ final Header newInstance = new Header(lineNumber);
for (final String key : headers.keySet()) {
newInstance.headers.put(key, headers.get(key).clone());
@@ -136,17 +118,30 @@ public class Header implements Cloneable {
return newInstance;
}
+ public static List<String> splitValuesByComma(final String headerValue) {
+ final List<String> singleValues = new ArrayList<String>();
+
+ String[] parts = headerValue.split(",");
+ for (final String value : parts) {
+ singleValues.add(value.trim());
+ }
+
+ return singleValues;
+ }
+
public static class HeaderField implements Cloneable {
- private String fieldName;
- private List<String> values;
+ private final String fieldName;
+ private final List<String> values;
+ private final int lineNumber;
- public HeaderField(final String fieldName) {
- this(fieldName, new ArrayList<String>());
+ public HeaderField(final String fieldName, final int lineNumber) {
+ this(fieldName, new ArrayList<String>(), lineNumber);
}
- public HeaderField(final String fieldName, final List<String> values) {
+ public HeaderField(final String fieldName, final List<String> values, final int lineNumber) {
this.fieldName = fieldName;
this.values = values;
+ this.lineNumber = lineNumber;
}
public String getFieldName() {
@@ -157,8 +152,37 @@ public class Header implements Cloneable {
return values;
}
- public void setValues(final List<String> values) {
- this.values = values;
+ public String getValue() {
+ final StringBuilder result = new StringBuilder();
+
+ for (final String value : values) {
+ result.append(value);
+ result.append(", ");
+ }
+
+ if (result.length() > 0) {
+ result.delete(result.length() - 2, result.length());
+ }
+
+ return result.toString();
+ }
+
+ public String getValueNotNull() {
+ final String value = getValue();
+
+ return (value == null) ? "" : value;
+ }
+
+ @Override
+ public HeaderField clone() {
+ List<String> newValues = new ArrayList<String>();
+ newValues.addAll(values);
+
+ return new HeaderField(fieldName, newValues, lineNumber);
+ }
+
+ public int getLineNumber() {
+ return lineNumber;
}
@Override
@@ -166,6 +190,8 @@ public class Header implements Cloneable {
final int prime = 31;
int result = 1;
result = prime * result + ((fieldName == null) ? 0 : fieldName.hashCode());
+ result = prime * result + lineNumber;
+ result = prime * result + ((values == null) ? 0 : values.hashCode());
return result;
}
@@ -188,15 +214,17 @@ public class Header implements Cloneable {
} else if (!fieldName.equals(other.fieldName)) {
return false;
}
+ if (lineNumber != other.lineNumber) {
+ return false;
+ }
+ if (values == null) {
+ if (other.values != null) {
+ return false;
+ }
+ } else if (!values.equals(other.values)) {
+ return false;
+ }
return true;
}
-
- @Override
- public HeaderField clone() {
- List<String> newValues = new ArrayList<String>();
- newValues.addAll(values);
-
- return new HeaderField(fieldName, newValues);
- }
}
}
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/f0dc0f74/odata2-lib/odata-core/src/main/resources/i18n.properties
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/resources/i18n.properties b/odata2-lib/odata-core/src/main/resources/i18n.properties
index a89c3e9..47e50a2 100644
--- a/odata2-lib/odata-core/src/main/resources/i18n.properties
+++ b/odata2-lib/odata-core/src/main/resources/i18n.properties
@@ -118,31 +118,30 @@ org.apache.olingo.odata2.api.ep.EntityProviderException.INVALID_DELETED_ENTRY_ME
##################################
# BatchParserexceptions
##################################
-org.apache.olingo.odata2.api.batch.BatchException.INVALID_CHANGESET_BOUNDARY=The boundary of the ChangeSet should be different from that used by the Batch: line '%1$s'.
+org.apache.olingo.odata2.api.batch.BatchException.INVALID_ACCEPT_LANGUAGE_HEADER=Invalid Accept-Language: '%1$s'.
+org.apache.olingo.odata2.api.batch.BatchException.INVALID_ACCEPT_HEADER=Invalid Accept header: '%1$s'.
org.apache.olingo.odata2.api.batch.BatchException.INVALID_BOUNDARY_DELIMITER=The boundary delimiter must begin with two hyphen characters: line '%1$s'.
-org.apache.olingo.odata2.api.batch.BatchException.MISSING_BOUNDARY_DELIMITER=Missing boundary delimiter at line '%1$s'.
-org.apache.olingo.odata2.api.batch.BatchException.MISSING_CLOSE_DELIMITER=Missing close delimiter at line '%1$s'.
-org.apache.olingo.odata2.api.batch.BatchException.INVALID_QUERY_OPERATION_METHOD=Invalid method: a Query Operation cannot contain insert, update or delete requests at line '%1$s'.
-org.apache.olingo.odata2.api.batch.BatchException.INVALID_CHANGESET_METHOD= Invalid method: a ChangeSet cannot contain retrieve requests at line '%1$s'.
-org.apache.olingo.odata2.api.batch.BatchException.INVALID_QUERY_PARAMETER=Invalid query parameters.
-org.apache.olingo.odata2.api.batch.BatchException.INVALID_URI=Invalid URI: line '%1$s'.
-org.apache.olingo.odata2.api.batch.BatchException.UNSUPPORTED_ABSOLUTE_PATH = An absolute-path in request line is not supported: line '%1$s'.
org.apache.olingo.odata2.api.batch.BatchException.INVALID_BOUNDARY=Invalid boundary at line '%1$s'.
-org.apache.olingo.odata2.api.batch.BatchException.NO_MATCH_WITH_BOUNDARY_STRING=The boundary string does not match the boundary from the Content-Type header field '%1$s': line '%2$s'.
-org.apache.olingo.odata2.api.batch.BatchException.MISSING_CONTENT_TYPE=No Content-Type field for MIME-header is present.
-org.apache.olingo.odata2.api.batch.BatchException.INVALID_CONTENT_TYPE=Content-Type should be '%1$s'.
-org.apache.olingo.odata2.api.batch.BatchException.MISSING_PARAMETER_IN_CONTENT_TYPE=The Content-Type field for multipart entities requires boundary parameter.
-org.apache.olingo.odata2.api.batch.BatchException.INVALID_CONTENT_TRANSFER_ENCODING=The Content-Transfer-Encoding should be binary.
-org.apache.olingo.odata2.api.batch.BatchException.INVALID_ACCEPT_HEADER=Invalid Accept header: '%1$s'.
-org.apache.olingo.odata2.api.batch.BatchException.INVALID_ACCEPT_LANGUAGE_HEADER=Invalid Accept-Language: '%1$s'.
org.apache.olingo.odata2.api.batch.BatchException.INVALID_HEADER=Invalid header: '%1$s' at line '%2$s'.
-org.apache.olingo.odata2.api.batch.BatchException.MISSING_BLANK_LINE=Expected empty line but was '%1$s': line '%2$s' .
+org.apache.olingo.odata2.api.batch.BatchException.INVALID_CONTENT_TRANSFER_ENCODING=The Content-Transfer-Encoding should be binary: line '%1$s'.
+org.apache.olingo.odata2.api.batch.BatchException.INVALID_CONTENT_TYPE=Content-Type should be '%1$s'.
+org.apache.olingo.odata2.api.batch.BatchException.INVALID_CHANGESET_BOUNDARY=The boundary of the ChangeSet should be different from that used by the Batch: line '%1$s'.
+org.apache.olingo.odata2.api.batch.BatchException.INVALID_CHANGESET_METHOD= Invalid method: a ChangeSet cannot contain retrieve requests at line '%1$s'.
+org.apache.olingo.odata2.api.batch.BatchException.INVALID_REQUEST_LINE=Invalid request line '%1$s' at line '%2$s'.
org.apache.olingo.odata2.api.batch.BatchException.INVALID_PATHINFO=PathInfo should not be null.
-org.apache.olingo.odata2.api.batch.BatchException.MISSING_METHOD=Missing method in request line '%1$s'.
+org.apache.olingo.odata2.api.batch.BatchException.INVALID_URI=Invalid URI: line '%1$s'.
+org.apache.olingo.odata2.api.batch.BatchException.INVALID_QUERY_OPERATION_METHOD=Invalid method: a Query Operation cannot contain insert, update or delete requests at line '%1$s'.
+org.apache.olingo.odata2.api.batch.BatchException.INVALID_QUERY_PARAMETER=Invalid query parameters.
+org.apache.olingo.odata2.api.batch.BatchException.MISSING_BLANK_LINE=Expected empty line but was '%1$s': line '%2$s' .
+org.apache.olingo.odata2.api.batch.BatchException.MISSING_BOUNDARY_DELIMITER=Missing boundary delimiter at line '%1$s'.
+org.apache.olingo.odata2.api.batch.BatchException.MISSING_CONTENT_TYPE=No Content-Type field for MIME-header is present.
+org.apache.olingo.odata2.api.batch.BatchException.MISSING_CLOSE_DELIMITER=Missing close delimiter at line '%1$s'.
org.apache.olingo.odata2.api.batch.BatchException.MISSING_MANDATORY_HEADER=Missing mandatory header '%1$s'.
-org.apache.olingo.odata2.api.batch.BatchException.INVALID_REQUEST_LINE=Invalid request line '%1$s' at line '%2$s'.
-org.apache.olingo.odata2.api.batch.BatchException.INVALID_REQUEST_LINE=Invalid status line '%1$s' at line '%2$s'.
+org.apache.olingo.odata2.api.batch.BatchException.MISSING_METHOD=Missing method in request line '%1$s'.
+org.apache.olingo.odata2.api.batch.BatchException.MISSING_PARAMETER_IN_CONTENT_TYPE=The Content-Type field for multipart entities requires boundary parameter.
+org.apache.olingo.odata2.api.batch.BatchException.NO_MATCH_WITH_BOUNDARY_STRING=The boundary string does not match the boundary from the Content-Type header field '%1$s': line '%2$s'.
org.apache.olingo.odata2.api.batch.BatchException.TRUNCATED_BODY=Body is truncated: line '%1$s'.
+org.apache.olingo.odata2.api.batch.BatchException.UNSUPPORTED_ABSOLUTE_PATH = An absolute-path in request line is not supported: line '%1$s'.
##################################
# HttpExceptions
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/f0dc0f74/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchParserCommonTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchParserCommonTest.java b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchParserCommonTest.java
index 56cbeeb..4369c1e 100644
--- a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchParserCommonTest.java
+++ b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchParserCommonTest.java
@@ -3,12 +3,12 @@ package org.apache.olingo.odata2.core.batch;
import static org.junit.Assert.*;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
import org.apache.olingo.odata2.api.batch.BatchException;
import org.apache.olingo.odata2.api.commons.HttpHeaders;
import org.apache.olingo.odata2.core.batch.v2.BatchParserCommon;
+import org.apache.olingo.odata2.core.batch.v2.BufferedReaderIncludingLineEndings.Line;
import org.apache.olingo.odata2.core.batch.v2.Header;
import org.junit.Test;
@@ -24,9 +24,7 @@ public class BatchParserCommonTest {
"content-type: Application/http" + CRLF,
"content-transfer-encoding: Binary" + CRLF
};
- List<String> message = new ArrayList<String>();
- message.addAll(Arrays.asList(messageRaw));
-
+ List<Line> message = toLineList(messageRaw);
final Header header = BatchParserCommon.consumeHeaders(message);
assertNotNull(header);
@@ -46,9 +44,7 @@ public class BatchParserCommonTest {
"content-type: Application/http" + CRLF,
"content-transfer-encoding: Binary" + CRLF
};
- List<String> message = new ArrayList<String>();
- message.addAll(Arrays.asList(messageRaw));
-
+ List<Line> message = toLineList(messageRaw);
final Header header = BatchParserCommon.consumeHeaders(message);
assertNotNull(header);
@@ -67,9 +63,7 @@ public class BatchParserCommonTest {
"content-type: Application/http" + CRLF,
"content-transfer-encoding: Binary" + CRLF
};
- List<String> message = new ArrayList<String>();
- message.addAll(Arrays.asList(messageRaw));
-
+ List<Line> message = toLineList(messageRaw);
final Header header = BatchParserCommon.consumeHeaders(message);
assertNotNull(header);
@@ -92,9 +86,7 @@ public class BatchParserCommonTest {
"content-type: Application/http" + CRLF,
"content-transfer-encoding: Binary" + CRLF
};
- List<String> message = new ArrayList<String>();
- message.addAll(Arrays.asList(messageRaw));
-
+ List<Line> message = toLineList(messageRaw);
final Header header = BatchParserCommon.consumeHeaders(message);
assertNotNull(header);
@@ -113,9 +105,7 @@ public class BatchParserCommonTest {
"content-type: Application/http" + CRLF,
"content-transfer-encoding: Binary" + CRLF
};
- List<String> message = new ArrayList<String>();
- message.addAll(Arrays.asList(messageRaw));
-
+ List<Line> message = toLineList(messageRaw);
final Header header = BatchParserCommon.consumeHeaders(message);
assertNotNull(header);
@@ -133,8 +123,7 @@ public class BatchParserCommonTest {
"content-type: Application/http" + CRLF,
"content-transfer-encoding: Binary" + CRLF
};
- List<String> message = new ArrayList<String>();
- message.addAll(Arrays.asList(messageRaw));
+ List<Line> message = toLineList(messageRaw);
final Header header = BatchParserCommon.consumeHeaders(message);
assertNotNull(header);
@@ -152,8 +141,7 @@ public class BatchParserCommonTest {
"content-type: Application/http" + CRLF,
"content-transfer-encoding: Binary" + CRLF
};
- List<String> message = new ArrayList<String>();
- message.addAll(Arrays.asList(messageRaw));
+ List<Line> message = toLineList(messageRaw);
final Header header = BatchParserCommon.consumeHeaders(message);
assertNotNull(header);
@@ -166,48 +154,59 @@ public class BatchParserCommonTest {
@Test
public void testRemoveEndingCRLF() {
String line = "Test\r\n";
- assertEquals("Test", BatchParserCommon.removeEndingCRLF(line));
+ assertEquals("Test", BatchParserCommon.removeEndingCRLF(new Line(line,1)).toString());
}
@Test
public void testRemoveLastEndingCRLF() {
String line = "Test\r\n\r\n";
- assertEquals("Test\r\n", BatchParserCommon.removeEndingCRLF(line));
+ assertEquals("Test\r\n", BatchParserCommon.removeEndingCRLF(new Line(line,1)).toString());
}
@Test
public void testRemoveEndingCRLFWithWS() {
String line = "Test\r\n ";
- assertEquals("Test", BatchParserCommon.removeEndingCRLF(line));
+ assertEquals("Test", BatchParserCommon.removeEndingCRLF(new Line(line,1)).toString());
}
@Test
public void testRemoveEndingCRLFNothingToRemove() {
String line = "Hallo\r\nBla";
- assertEquals("Hallo\r\nBla", BatchParserCommon.removeEndingCRLF(line));
+ assertEquals("Hallo\r\nBla", BatchParserCommon.removeEndingCRLF(new Line(line,1)).toString());
}
@Test
public void testRemoveEndingCRLFAll() {
String line = "\r\n";
- assertEquals("", BatchParserCommon.removeEndingCRLF(line));
+ assertEquals("", BatchParserCommon.removeEndingCRLF(new Line(line,1)).toString());
}
@Test
public void testRemoveEndingCRLFSpace() {
String line = "\r\n ";
- assertEquals("", BatchParserCommon.removeEndingCRLF(line));
+ assertEquals("", BatchParserCommon.removeEndingCRLF(new Line(line,1)).toString());
}
@Test
public void testRemoveLastEndingCRLFWithWS() {
String line = "Test \r\n";
- assertEquals("Test ", BatchParserCommon.removeEndingCRLF(line));
+ assertEquals("Test ", BatchParserCommon.removeEndingCRLF(new Line(line,1)).toString());
}
@Test
public void testRemoveLastEndingCRLFWithWSLong() {
String line = "Test \r\nTest2 \r\n";
- assertEquals("Test \r\nTest2 ", BatchParserCommon.removeEndingCRLF(line));
+ assertEquals("Test \r\nTest2 ", BatchParserCommon.removeEndingCRLF(new Line(line,1)).toString());
+ }
+
+ private List<Line> toLineList(String[] messageRaw) {
+ final List<Line> lineList = new ArrayList<Line>();
+ int counter = 1;
+
+ for(final String currentLine : messageRaw) {
+ lineList.add(new Line(currentLine, counter++));
+ }
+
+ return lineList;
}
}
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/f0dc0f74/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestParserTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestParserTest.java b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestParserTest.java
index 4cd0b67..142d355 100644
--- a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestParserTest.java
+++ b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestParserTest.java
@@ -44,9 +44,6 @@ import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
-/**
- *
- */
public class BatchRequestParserTest {
private static final String CRLF = "\r\n";
@@ -257,7 +254,7 @@ public class BatchRequestParserTest {
@Test(expected = BatchException.class)
public void testBoundaryParameterWithoutQuota() throws BatchException {
- String invalidContentType = "multipart;boundary=batch_1740-bb:84-2f7f";
+ String invalidContentType = "multipart/mixed;boundary=batch_1740-bb:84-2f7f";
String batch = "--batch_1740-bb:84-2f7f" + CRLF
+ GET_REQUEST
+ "--batch_1740-bb:84-2f7f--";
@@ -607,32 +604,6 @@ public class BatchRequestParserTest {
}
@SuppressWarnings("unused")
- @Test(expected = BatchException.class)
- @Ignore("This header should not be validated")
- public void testNegativeContentLength() throws BatchException, IOException {
- String batch = ""
- + "--batch_8194-cf13-1f56" + CRLF
- + "Content-Type: multipart/mixed; boundary=changeset_f980-1cb6-94dd" + CRLF
- + "Content-Length: -2" + CRLF
- + CRLF
- + "--changeset_f980-1cb6-94dd" + CRLF
- + MIME_HEADERS
- + "Content-ID: " + PUT_MIME_HEADER_CONTENT_ID + CRLF
- + CRLF
- + "PUT $" + CONTENT_ID_REFERENCE + "/EmployeeName HTTP/1.1" + CRLF
- + "Content-Type: application/json;odata=verbose" + CRLF
- + "Content-Id:" + PUT_REQUEST_HEADER_CONTENT_ID + CRLF
- + CRLF
- + "{\"EmployeeName\":\"Peter Fall\"}" + CRLF
- + "--changeset_f980-1cb6-94dd--" + CRLF
- + CRLF
- + "--batch_8194-cf13-1f56--";
- InputStream in = new ByteArrayInputStream(batch.getBytes());
- BatchParser parser = new BatchParser(contentType, batchProperties, true);
- List<BatchRequestPart> batchRequestParts = parser.parseBatchRequest(in);
- }
-
- @SuppressWarnings("unused")
@Test
public void testNegativeContentLengthChangeSet() throws BatchException, IOException {
String batch = ""
@@ -747,44 +718,6 @@ public class BatchRequestParserTest {
}
@Test(expected = BatchException.class)
- @Ignore("This header should not be validated")
- public void testCutChangeSetDelimiter() throws BatchException, IOException {
- String batch = ""
- + "--batch_8194-cf13-1f56" + CRLF
- + "Content-Type: multipart/mixed; boundary=changeset_f980-1cb6-94dd" + CRLF
- + "Content-Length: 582" + CRLF
- + CRLF
- + "--changeset_f980-1cb6-94dd" + CRLF
- + MIME_HEADERS
- + "Content-ID: " + PUT_MIME_HEADER_CONTENT_ID + CRLF
- + CRLF
- + "PUT $" + CONTENT_ID_REFERENCE + "/EmployeeName HTTP/1.1" + CRLF
- + "Content-Type: application/json;odata=verbose" + CRLF
- + "Content-Id:" + PUT_REQUEST_HEADER_CONTENT_ID + CRLF
- + "Content-Length: 10" + CRLF
- + CRLF
- + "{\"EmployeeName\":\"Peter Fall\"}" + CRLF
- + CRLF
- + "--changeset_f980-1cb6-94dd" + CRLF
- + MIME_HEADERS
- + "Content-ID: " + PUT_MIME_HEADER_CONTENT_ID + CRLF
- + CRLF
- + "PUT $" + CONTENT_ID_REFERENCE + "/EmployeeName HTTP/1.1" + CRLF
- + "Content-Type: application/json;odata=verbose" + CRLF
- + "Content-Id:" + PUT_REQUEST_HEADER_CONTENT_ID + CRLF
- + "Content-Length: 100000" + CRLF
- + CRLF
- + "{\"EmployeeName\":\"Peter Fall\"}" + CRLF
- + "--changeset_f980-1cb6-94dd--" + CRLF
- + CRLF
- + "--batch_8194-cf13-1f56--";
-
- InputStream in = new ByteArrayInputStream(batch.getBytes());
- BatchParser parser = new BatchParser(contentType, batchProperties, true);
- parser.parseBatchRequest(in);
- }
-
- @Test(expected = BatchException.class)
public void testNonNumericContentLength() throws BatchException {
String batch = ""
+ "--batch_8194-cf13-1f56" + CRLF
@@ -1138,7 +1071,20 @@ public class BatchRequestParserTest {
assertEquals("{\"EmployeeName\":\"Peter Fall\"}",
inputStreamToString(changeSetPart.getRequests().get(1).getBody()));
}
+
+ @Test
+ public void testLargeBatch() throws BatchException, IOException {
+ String fileName = "/batchLarge.batch";
+ InputStream in = ClassLoader.class.getResourceAsStream(fileName);
+ if (in == null) {
+ throw new IOException("Requested file '" + fileName + "' was not found.");
+ }
+
+ BatchParser parser = new BatchParser(contentType, batchProperties, true);
+ parser.parseBatchRequest(in);
+ }
+
private List<BatchRequestPart> parse(final String batch) throws BatchException {
InputStream in = new ByteArrayInputStream(batch.getBytes());
BatchParser parser = new BatchParser(contentType, batchProperties, true);
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/f0dc0f74/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestTest.java b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestTest.java
index 6c604f8..bcf13e4 100644
--- a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestTest.java
+++ b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestTest.java
@@ -132,7 +132,6 @@ public class BatchRequestTest {
}
@Test
- @Ignore
// TODO
/*
* --batch_123
@@ -146,8 +145,8 @@ public class BatchRequestTest {
* ...
* ....
*/
- public
- void testBatchWithGetAndPost() throws BatchException, IOException {
+ @Ignore
+ public void testBatchWithGetAndPost() throws BatchException, IOException {
List<BatchPart> batch = new ArrayList<BatchPart>();
Map<String, String> headers = new HashMap<String, String>();
headers.put("Accept", "application/json");
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/f0dc0f74/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchTransformatorCommonTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchTransformatorCommonTest.java b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchTransformatorCommonTest.java
index e98a295..7437caf 100644
--- a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchTransformatorCommonTest.java
+++ b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchTransformatorCommonTest.java
@@ -50,7 +50,7 @@ public class BatchTransformatorCommonTest {
@Test(expected = BatchException.class)
public void testValidateContentTypeMissingHeader() throws BatchException {
- final Header headers = new Header();
+ final Header headers = new Header(1);
BatchTransformatorCommon.validateContentType(headers);
}
@@ -82,7 +82,7 @@ public class BatchTransformatorCommonTest {
@Test(expected = BatchException.class)
public void testValidateContentTransferEncodingMissingHeader() throws BatchException {
- final Header headers = new Header();
+ final Header headers = new Header(1);
BatchTransformatorCommon.validateContentTransferEncoding(headers, true);
}
@@ -96,8 +96,8 @@ public class BatchTransformatorCommonTest {
}
private Header makeHeaders(final String headerName, final List<String> values) {
- final Header headers = new Header();
- headers.addHeader(headerName, values);
+ final Header headers = new Header(1);
+ headers.addHeader(headerName, values, 1);
return headers;
}
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/f0dc0f74/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BufferedReaderIncludingLineEndingsTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BufferedReaderIncludingLineEndingsTest.java b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BufferedReaderIncludingLineEndingsTest.java
index bd3607a..482dc3b 100644
--- a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BufferedReaderIncludingLineEndingsTest.java
+++ b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BufferedReaderIncludingLineEndingsTest.java
@@ -9,6 +9,7 @@ import java.io.UnsupportedEncodingException;
import java.util.List;
import org.apache.olingo.odata2.core.batch.v2.BufferedReaderIncludingLineEndings;
+import org.apache.olingo.odata2.core.batch.v2.BufferedReaderIncludingLineEndings.Line;
import org.junit.Test;
public class BufferedReaderIncludingLineEndingsTest {
@@ -422,20 +423,20 @@ public class BufferedReaderIncludingLineEndingsTest {
@Test
public void testToList() throws IOException {
BufferedReaderIncludingLineEndings reader = create(TEXT_COMBINED);
- List<String> stringList = reader.toList();
+ List<Line> stringList = reader.toList();
assertEquals(11, stringList.size());
- assertEquals("Test\r", stringList.get(0));
- assertEquals("Test2\r\n", stringList.get(1));
- assertEquals("Test3\n", stringList.get(2));
- assertEquals("Test4\r", stringList.get(3));
- assertEquals("\r", stringList.get(4));
- assertEquals("\r\n", stringList.get(5));
- assertEquals("\r\n", stringList.get(6));
- assertEquals("Test5\n", stringList.get(7));
- assertEquals("Test6\r\n", stringList.get(8));
- assertEquals("Test7\n", stringList.get(9));
- assertEquals("\n", stringList.get(10));
+ assertEquals("Test\r", stringList.get(0).toString());
+ assertEquals("Test2\r\n", stringList.get(1).toString());
+ assertEquals("Test3\n", stringList.get(2).toString());
+ assertEquals("Test4\r", stringList.get(3).toString());
+ assertEquals("\r", stringList.get(4).toString());
+ assertEquals("\r\n", stringList.get(5).toString());
+ assertEquals("\r\n", stringList.get(6).toString());
+ assertEquals("Test5\n", stringList.get(7).toString());
+ assertEquals("Test6\r\n", stringList.get(8).toString());
+ assertEquals("Test7\n", stringList.get(9).toString());
+ assertEquals("\n", stringList.get(10).toString());
reader.close();
}
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/f0dc0f74/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/HeaderTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/HeaderTest.java b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/HeaderTest.java
index 128aa2e..bfe7b24 100644
--- a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/HeaderTest.java
+++ b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/HeaderTest.java
@@ -15,8 +15,8 @@ public class HeaderTest {
@Test
public void test() {
- Header header = new Header();
- header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED);
+ Header header = new Header(1);
+ header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED, 1);
assertEquals(HttpContentType.MULTIPART_MIXED, header.getHeader(HttpHeaders.CONTENT_TYPE));
assertEquals(1, header.getHeaders(HttpHeaders.CONTENT_TYPE).size());
@@ -25,7 +25,7 @@ public class HeaderTest {
@Test
public void testNotAvailable() {
- Header header = new Header();
+ Header header = new Header(1);
assertNull(header.getHeader(HttpHeaders.CONTENT_TYPE));
assertEquals(0, header.getHeaders(HttpHeaders.CONTENT_TYPE).size());
@@ -34,8 +34,8 @@ public class HeaderTest {
@Test
public void testCaseInsensitive() {
- Header header = new Header();
- header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED);
+ Header header = new Header(1);
+ header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED, 1);
assertEquals(HttpContentType.MULTIPART_MIXED, header.getHeader("cOnTenT-TyPE"));
assertEquals(1, header.getHeaders("cOnTenT-TyPE").size());
@@ -44,9 +44,9 @@ public class HeaderTest {
@Test
public void testDuplicatedAdd() {
- Header header = new Header();
- header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED);
- header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED);
+ Header header = new Header(1);
+ header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED, 1);
+ header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED, 2);
assertEquals(HttpContentType.MULTIPART_MIXED, header.getHeader(HttpHeaders.CONTENT_TYPE));
assertEquals(1, header.getHeaders(HttpHeaders.CONTENT_TYPE).size());
@@ -55,16 +55,16 @@ public class HeaderTest {
@Test
public void testMatcher() {
- Header header = new Header();
- header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED + ";boundary=123");
+ Header header = new Header(1);
+ header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED + ";boundary=123", 1);
assertTrue(header.isHeaderMatching(HttpHeaders.CONTENT_TYPE, BatchParserCommon.PATTERN_MULTIPART_BOUNDARY));
}
@Test
public void testFieldName() {
- Header header = new Header();
- header.addHeader("MyFieldNamE", "myValue");
+ Header header = new Header(0);
+ header.addHeader("MyFieldNamE", "myValue", 1);
assertEquals("MyFieldNamE", header.getHeaderField("myfieldname").getFieldName());
assertEquals("MyFieldNamE", header.toSingleMap().keySet().toArray(new String[0])[0]);
@@ -76,8 +76,8 @@ public class HeaderTest {
@Test
public void testDeepCopy() {
- Header header = new Header();
- header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED + ";boundary=123");
+ Header header = new Header(1);
+ header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED + ";boundary=123", 1);
Header copy = header.clone();
assertEquals(header.getHeaders(HttpHeaders.CONTENT_TYPE), copy.getHeaders(HttpHeaders.CONTENT_TYPE));
@@ -90,25 +90,25 @@ public class HeaderTest {
@Test
public void testMatcherNoHeader() {
- Header header = new Header();
+ Header header = new Header(1);
assertFalse(header.isHeaderMatching(HttpHeaders.CONTENT_TYPE, BatchParserCommon.PATTERN_MULTIPART_BOUNDARY));
}
@Test
public void testMatcherFail() {
- Header header = new Header();
- header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED + ";boundary=123");
+ Header header = new Header(1);
+ header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED + ";boundary=123", 1);
assertFalse(header.isHeaderMatching(HttpHeaders.CONTENT_TYPE, BatchParserCommon.PATTERN_HEADER_LINE));
}
@Test
public void testDuplicatedAddList() {
- Header header = new Header();
- header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED);
+ Header header = new Header(1);
+ header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED, 1);
header.addHeader(HttpHeaders.CONTENT_TYPE, Arrays.asList(new String[] { HttpContentType.MULTIPART_MIXED,
- HttpContentType.APPLICATION_ATOM_SVC }));
+ HttpContentType.APPLICATION_ATOM_SVC }), 2);
assertEquals(HttpContentType.MULTIPART_MIXED + ", " + HttpContentType.APPLICATION_ATOM_SVC, header
.getHeader(HttpHeaders.CONTENT_TYPE));
@@ -119,9 +119,9 @@ public class HeaderTest {
@Test
public void testRemove() {
- Header header = new Header();
- header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED);
- header.removeHeaders(HttpHeaders.CONTENT_TYPE);
+ Header header = new Header(1);
+ header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED, 1);
+ header.removeHeader(HttpHeaders.CONTENT_TYPE);
assertNull(header.getHeader(HttpHeaders.CONTENT_TYPE));
assertEquals(0, header.getHeaders(HttpHeaders.CONTENT_TYPE).size());
@@ -129,10 +129,10 @@ public class HeaderTest {
@Test
public void testMultipleValues() {
- Header header = new Header();
- header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED);
- header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.APPLICATION_ATOM_SVC);
- header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.APPLICATION_ATOM_XML);
+ Header header = new Header(1);
+ header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED, 1);
+ header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.APPLICATION_ATOM_SVC, 2);
+ header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.APPLICATION_ATOM_XML, 3);
final String fullHeaderString =
HttpContentType.MULTIPART_MIXED + ", " + HttpContentType.APPLICATION_ATOM_SVC + ", "
[2/4] git commit: Header class refactoring
Posted by ch...@apache.org.
Header class refactoring
Signed-off-by: Christian Amend <ch...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata2/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata2/commit/05d20c1f
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata2/tree/05d20c1f
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata2/diff/05d20c1f
Branch: refs/heads/olingo436BatchRefactoring
Commit: 05d20c1fa078f2c445b4fe30ab96d4a5f8d2b585
Parents: 1f90b73
Author: Christian Holzer <c....@sap.com>
Authored: Fri Oct 3 01:34:45 2014 +0200
Committer: Christian Amend <ch...@apache.org>
Committed: Mon Oct 6 13:54:38 2014 +0200
----------------------------------------------------------------------
.../odata2/core/batch/v2/BatchBodyPart.java | 24 +--
.../odata2/core/batch/v2/BatchParserCommon.java | 135 +------------
.../olingo/odata2/core/batch/v2/BatchPart.java | 6 +-
.../core/batch/v2/BatchQueryOperation.java | 6 +-
.../batch/v2/BatchRequestTransformator.java | 121 ++++-------
.../batch/v2/BatchResponseTransformator.java | 61 +++---
.../core/batch/v2/BatchTransformatorCommon.java | 47 ++---
.../olingo/odata2/core/batch/v2/Header.java | 202 +++++++++++++++++++
.../core/batch/BatchParserCommonTest.java | 60 +++---
.../batch/BatchTransformatorCommonTest.java | 34 ++--
.../olingo/odata2/core/batch/HeaderTest.java | 161 +++++++++++++++
11 files changed, 509 insertions(+), 348 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/05d20c1f/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchBodyPart.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchBodyPart.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchBodyPart.java
index 4edcf45..f74ea85 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchBodyPart.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchBodyPart.java
@@ -20,19 +20,16 @@ package org.apache.olingo.odata2.core.batch.v2;
import java.util.LinkedList;
import java.util.List;
-import java.util.Locale;
-import java.util.Map;
import org.apache.olingo.odata2.api.batch.BatchException;
import org.apache.olingo.odata2.api.commons.HttpHeaders;
-import org.apache.olingo.odata2.core.batch.v2.BatchParserCommon.HeaderField;
public class BatchBodyPart implements BatchPart {
final private String boundary;
final private boolean isStrict;
final List<String> remainingMessage = new LinkedList<String>();
- private Map<String, HeaderField> headers;
+ private Header headers;
private boolean isChangeSet;
private List<BatchQueryOperation> requests;
@@ -53,15 +50,15 @@ public class BatchBodyPart implements BatchPart {
return this;
}
- private boolean isChangeSet(final Map<String, HeaderField> headers) throws BatchException {
- final HeaderField contentTypeField = headers.get(HttpHeaders.CONTENT_TYPE.toLowerCase(Locale.ENGLISH));
+ private boolean isChangeSet(final Header headers) throws BatchException {
+ final List<String> contentTypes = headers.getHeaders(HttpHeaders.CONTENT_TYPE);
boolean isChangeSet = false;
- if (contentTypeField == null || contentTypeField.getValues().size() == 0) {
+ if (contentTypes.size() == 0) {
throw new BatchException(BatchException.MISSING_CONTENT_TYPE);
}
- for (String contentType : contentTypeField.getValues()) {
+ for (String contentType : contentTypes) {
if (isContentTypeMultiPartMixed(contentType)) {
isChangeSet = true;
}
@@ -97,7 +94,7 @@ public class BatchBodyPart implements BatchPart {
private List<List<String>> splitChangeSet(final List<String> remainingMessage)
throws BatchException {
- final String changeSetBoundary = BatchParserCommon.getBoundary(getContentType());
+ final String changeSetBoundary = BatchParserCommon.getBoundary(headers.getHeaderNotNull(HttpHeaders.CONTENT_TYPE));
validateChangeSetBoundary(changeSetBoundary);
return BatchParserCommon.splitMessageByBoundary(remainingMessage, changeSetBoundary);
@@ -117,15 +114,8 @@ public class BatchBodyPart implements BatchPart {
}
}
- private String getContentType() {
- HeaderField contentTypeField = headers.get(HttpHeaders.CONTENT_TYPE.toLowerCase(Locale.ENGLISH));
-
- return (contentTypeField != null && contentTypeField.getValues().size() > 0) ? contentTypeField.getValues().get(0)
- : "";
- }
-
@Override
- public Map<String, HeaderField> getHeaders() {
+ public Header getHeaders() {
return headers;
}
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/05d20c1f/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchParserCommon.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchParserCommon.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchParserCommon.java
index 8b7f62a..df62994 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchParserCommon.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchParserCommon.java
@@ -23,7 +23,6 @@ import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
@@ -148,8 +147,8 @@ public class BatchParserCommon {
}
}
- public static Map<String, HeaderField> consumeHeaders(final List<String> remainingMessage) throws BatchException {
- final Map<String, HeaderField> headers = new HashMap<String, HeaderField>();
+ public static Header consumeHeaders(final List<String> remainingMessage) throws BatchException {
+ final Header headers = new Header();
boolean isHeader = true;
final Iterator<String> iter = remainingMessage.iterator();
final AcceptParser acceptParser = new AcceptParser();
@@ -157,59 +156,30 @@ public class BatchParserCommon {
while (iter.hasNext() && isHeader) {
currentLine = iter.next();
- Matcher headerMatcher = PATTERN_HEADER_LINE.matcher(currentLine);
+ final Matcher headerMatcher = PATTERN_HEADER_LINE.matcher(currentLine);
if (headerMatcher.matches() && headerMatcher.groupCount() == 2) {
iter.remove();
String headerName = headerMatcher.group(1).trim();
- String headerNameLowerCase = headerName.toLowerCase(Locale.ENGLISH);
String headerValue = headerMatcher.group(2).trim();
- if (HttpHeaders.ACCEPT.equalsIgnoreCase(headerNameLowerCase)) {
+ if (HttpHeaders.ACCEPT.equalsIgnoreCase(headerName)) {
acceptParser.addAcceptHeaderValue(headerValue);
- } else if (HttpHeaders.ACCEPT_LANGUAGE.equalsIgnoreCase(headerNameLowerCase)) {
+ } else if (HttpHeaders.ACCEPT_LANGUAGE.equalsIgnoreCase(headerName)) {
acceptParser.addAcceptLanguageHeaderValue(headerValue);
} else {
- addHeaderValue(headers, headerName, headerNameLowerCase, headerValue);
+ headers.addHeader(headerName, Header.splitValuesByComma(headerValue));
}
} else {
isHeader = false;
}
}
- final List<String> acceptHeader = acceptParser.parseAcceptHeaders();
- headers.put(HttpHeaders.ACCEPT.toLowerCase(), new HeaderField(HttpHeaders.ACCEPT, acceptHeader));
+ headers.addHeader(HttpHeaders.ACCEPT, acceptParser.parseAcceptHeaders());
+ headers.addHeader(HttpHeaders.ACCEPT_LANGUAGE, acceptParser.parseAcceptableLanguages());
- final List<String> acceptLanguageHeader = acceptParser.parseAcceptableLanguages();
- headers.put(HttpHeaders.ACCEPT_LANGUAGE.toLowerCase(), new HeaderField(HttpHeaders.ACCEPT_LANGUAGE,
- acceptLanguageHeader));
-
- return Collections.unmodifiableMap(headers);
- }
-
- private static void addHeaderValue(final Map<String, HeaderField> headers, final String headerName,
- final String headerNameLowerCase, final String headerValue) {
- HeaderField headerField = headers.get(headerNameLowerCase);
- headerField = headerField == null ? new HeaderField(headerName) : headerField;
- headers.put(headerNameLowerCase, headerField);
-
- for (final String singleValue : splitHeaderValuesByComma(headerValue)) {
- if (!headerField.getValues().contains(singleValue)) {
- headerField.getValues().add(singleValue);
- }
- }
- }
-
- private static List<String> splitHeaderValuesByComma(final String headerValue) {
- final List<String> singleValues = new ArrayList<String>();
-
- String[] parts = headerValue.split(",");
- for (final String value : parts) {
- singleValues.add(value.trim());
- }
-
- return singleValues;
+ return headers;
}
public static void consumeBlankLine(final List<String> remainingMessage, final boolean isStrict)
@@ -338,91 +308,4 @@ public class BatchParserCommon {
return boundary;
}
-
- public static Map<String, String> headerFieldMapToSingleMap(final Map<String, HeaderField> headers) {
- final Map<String, String> singleMap = new HashMap<String, String>();
-
- for (final String key : headers.keySet()) {
- HeaderField field = headers.get(key);
- String value = field.getValues().size() > 0 ? field.getValues().get(0) : "";
- singleMap.put(field.getFieldName(), value);
- }
-
- return singleMap;
- }
-
- public static Map<String, List<String>> headerFieldMapToMultiMap(final Map<String, HeaderField> headers) {
- final Map<String, List<String>> singleMap = new HashMap<String, List<String>>();
-
- for (final String key : headers.keySet()) {
- HeaderField field = headers.get(key);
- singleMap.put(field.getFieldName(), field.getValues());
- }
-
- return singleMap;
- }
-
- public static class HeaderField implements Cloneable {
- private String fieldName;
- private List<String> values;
-
- public HeaderField(final String fieldName) {
- this(fieldName, new ArrayList<String>());
- }
-
- public HeaderField(final String fieldName, final List<String> values) {
- this.fieldName = fieldName;
- this.values = values;
- }
-
- public String getFieldName() {
- return fieldName;
- }
-
- public List<String> getValues() {
- return values;
- }
-
- public void setValues(final List<String> values) {
- this.values = values;
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((fieldName == null) ? 0 : fieldName.hashCode());
- return result;
- }
-
- @Override
- public boolean equals(final Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null) {
- return false;
- }
- if (getClass() != obj.getClass()) {
- return false;
- }
- HeaderField other = (HeaderField) obj;
- if (fieldName == null) {
- if (other.fieldName != null) {
- return false;
- }
- } else if (!fieldName.equals(other.fieldName)) {
- return false;
- }
- return true;
- }
-
- @Override
- public HeaderField clone() {
- List<String> newValues = new ArrayList<String>();
- newValues.addAll(values);
-
- return new HeaderField(fieldName, newValues);
- }
- }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/05d20c1f/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchPart.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchPart.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchPart.java
index 258f48a..69f211f 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchPart.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchPart.java
@@ -18,12 +18,8 @@
******************************************************************************/
package org.apache.olingo.odata2.core.batch.v2;
-import java.util.Map;
-
-import org.apache.olingo.odata2.core.batch.v2.BatchParserCommon.HeaderField;
-
public interface BatchPart {
- public Map<String, HeaderField> getHeaders();
+ public Header getHeaders();
public boolean isStrict();
}
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/05d20c1f/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchQueryOperation.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchQueryOperation.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchQueryOperation.java
index 5176bb8..87dcb23 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchQueryOperation.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchQueryOperation.java
@@ -19,16 +19,14 @@
package org.apache.olingo.odata2.core.batch.v2;
import java.util.List;
-import java.util.Map;
import org.apache.olingo.odata2.api.batch.BatchException;
-import org.apache.olingo.odata2.core.batch.v2.BatchParserCommon.HeaderField;
public class BatchQueryOperation implements BatchPart {
protected final boolean isStrict;
protected String httpStatusLine;
- protected Map<String, HeaderField> headers;
+ protected Header headers;
protected List<String> body;
protected int bodySize;
protected List<String> message;
@@ -71,7 +69,7 @@ public class BatchQueryOperation implements BatchPart {
}
@Override
- public Map<String, HeaderField> getHeaders() {
+ public Header getHeaders() {
return headers;
}
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/05d20c1f/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchRequestTransformator.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchRequestTransformator.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchRequestTransformator.java
index 5169575..a49a2e5 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchRequestTransformator.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchRequestTransformator.java
@@ -22,12 +22,10 @@ import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
-import java.util.Map;
import java.util.Set;
import org.apache.olingo.odata2.api.batch.BatchException;
@@ -40,7 +38,6 @@ import org.apache.olingo.odata2.api.processor.ODataRequest.ODataRequestBuilder;
import org.apache.olingo.odata2.api.uri.PathInfo;
import org.apache.olingo.odata2.core.batch.BatchHelper;
import org.apache.olingo.odata2.core.batch.BatchRequestPartImpl;
-import org.apache.olingo.odata2.core.batch.v2.BatchParserCommon.HeaderField;
public class BatchRequestTransformator implements BatchTransformator {
@@ -55,7 +52,7 @@ public class BatchRequestTransformator implements BatchTransformator {
final List<ODataRequest> requests = new LinkedList<ODataRequest>();
final List<BatchParserResult> resultList = new ArrayList<BatchParserResult>();
- validateBodyPartHeaders(bodyPart);
+ validateHeader(bodyPart, false);
for (BatchQueryOperation queryOperation : bodyPart.getRequests()) {
requests.add(processQueryOperation(bodyPart, pathInfo, baseUri, queryOperation));
@@ -65,11 +62,11 @@ public class BatchRequestTransformator implements BatchTransformator {
return resultList;
}
- private void validateBodyPartHeaders(final BatchBodyPart bodyPart) throws BatchException {
- Map<String, HeaderField> headers = bodyPart.getHeaders();
+ private void validateHeader(final BatchPart bodyPart, boolean isChangeSet) throws BatchException {
+ Header headers = bodyPart.getHeaders();
BatchTransformatorCommon.validateContentType(headers);
- BatchTransformatorCommon.validateContentTransferEncoding(headers, false);
+ BatchTransformatorCommon.validateContentTransferEncoding(headers, isChangeSet);
}
private ODataRequest processQueryOperation(final BatchBodyPart bodyPart, final PathInfo pathInfo,
@@ -77,24 +74,18 @@ public class BatchRequestTransformator implements BatchTransformator {
if (bodyPart.isChangeSet()) {
BatchQueryOperation encapsulatedQueryOperation = ((BatchChangeSetPart) queryOperation).getRequest();
- Map<String, HeaderField> headers = transformHeader(encapsulatedQueryOperation, queryOperation);
- validateChangeSetMultipartMimeHeaders(queryOperation, encapsulatedQueryOperation);
+ Header headers = transformHeader(encapsulatedQueryOperation, queryOperation);
+ validateHeader(queryOperation, true);
return createRequest(queryOperation, headers, pathInfo, baseUri, bodyPart.isChangeSet());
} else {
- Map<String, HeaderField> headers = transformHeader(queryOperation, bodyPart);
+ Header headers = transformHeader(queryOperation, bodyPart);
return createRequest(queryOperation, headers, pathInfo, baseUri, bodyPart.isChangeSet());
}
}
- private void validateChangeSetMultipartMimeHeaders(final BatchQueryOperation queryOperation,
- final BatchQueryOperation encapsulatedQueryOperation) throws BatchException {
- BatchTransformatorCommon.validateContentType(queryOperation.getHeaders());
- BatchTransformatorCommon.validateContentTransferEncoding(queryOperation.getHeaders(), true);
- }
-
- private ODataRequest createRequest(final BatchQueryOperation operation, final Map<String, HeaderField> headers,
+ private ODataRequest createRequest(final BatchQueryOperation operation, final Header headers,
final PathInfo pathInfo, final String baseUri, final boolean isChangeSet) throws BatchException {
ODataHttpMethod httpMethod = getHttpMethod(operation.getHttpStatusLine());
@@ -104,14 +95,18 @@ public class BatchRequestTransformator implements BatchTransformator {
ODataRequestBuilder requestBuilder = ODataRequest.method(httpMethod)
.acceptableLanguages(getAcceptLanguageHeaders(headers))
- .acceptHeaders(getAcceptHeaders(headers))
+ .acceptHeaders(headers.getHeaders(HttpHeaders.ACCEPT))
.allQueryParameters(BatchParserCommon.parseQueryParameter(operation.getHttpStatusLine()))
.body(bodyStrean)
- .requestHeaders(BatchParserCommon.headerFieldMapToMultiMap(headers))
+ .requestHeaders(headers.toMultiMap())
.pathInfo(BatchParserCommon.parseRequestUri(operation.getHttpStatusLine(), pathInfo, baseUri));
-
- addContentTypeHeader(requestBuilder, headers);
-
+
+ final String contentType =headers.getHeader(HttpHeaders.CONTENT_TYPE);
+ if(contentType != null) {
+ requestBuilder.contentType(contentType);
+ }
+
+
return requestBuilder.build();
}
@@ -127,7 +122,7 @@ public class BatchRequestTransformator implements BatchTransformator {
|| (operation.getBody().size() == 1 && !operation.getBody().get(0).trim().equals(""));
}
- private InputStream getBodyStream(final BatchQueryOperation operation, final Map<String, HeaderField> headers,
+ private InputStream getBodyStream(final BatchQueryOperation operation, Header headers,
final ODataHttpMethod httpMethod) throws BatchException {
if (HTTP_BATCH_METHODS.contains(httpMethod.toString())) {
@@ -143,27 +138,18 @@ public class BatchRequestTransformator implements BatchTransformator {
}
}
- private Map<String, HeaderField> transformHeader(final BatchPart operation, final BatchPart parentPart) {
- final Map<String, HeaderField> headers = new HashMap<String, HeaderField>();
- final Map<String, HeaderField> operationHeader = operation.getHeaders();
- final Map<String, HeaderField> parentHeaders = parentPart.getHeaders();
+ private Header transformHeader(final BatchPart operation, final BatchPart parentPart) {
+ final Header headers = operation.getHeaders().clone();
+ headers.removeHeaders(BatchHelper.HTTP_CONTENT_ID);
+ final List<String> operationContentIds = operation.getHeaders().getHeaders(BatchHelper.HTTP_CONTENT_ID);
+ final List<String> parentContentIds = parentPart.getHeaders().getHeaders(BatchHelper.HTTP_CONTENT_ID);
- for (final String key : operation.getHeaders().keySet()) {
- headers.put(key, operation.getHeaders().get(key).clone());
+ if (operationContentIds.size() != 0) {
+ headers.addHeader(BatchHelper.REQUEST_HEADER_CONTENT_ID, operationContentIds);
}
- headers.remove(BatchHelper.HTTP_CONTENT_ID.toLowerCase(Locale.ENGLISH));
-
- if (operationHeader.containsKey(BatchHelper.HTTP_CONTENT_ID.toLowerCase(Locale.ENGLISH))) {
- HeaderField operationContentField = operationHeader.get(BatchHelper.HTTP_CONTENT_ID.toLowerCase());
- headers.put(BatchHelper.REQUEST_HEADER_CONTENT_ID.toLowerCase(Locale.ENGLISH), new HeaderField(
- BatchHelper.REQUEST_HEADER_CONTENT_ID, operationContentField.getValues()));
- }
-
- if (parentHeaders.containsKey(BatchHelper.HTTP_CONTENT_ID.toLowerCase(Locale.ENGLISH))) {
- HeaderField parentContentField = parentHeaders.get(BatchHelper.HTTP_CONTENT_ID.toLowerCase());
- headers.put(BatchHelper.MIME_HEADER_CONTENT_ID.toLowerCase(Locale.ENGLISH), new HeaderField(
- BatchHelper.MIME_HEADER_CONTENT_ID, parentContentField.getValues()));
+ if (parentContentIds.size() != 0) {
+ headers.addHeader(BatchHelper.MIME_HEADER_CONTENT_ID, parentContentIds);
}
return headers;
@@ -179,52 +165,19 @@ public class BatchRequestTransformator implements BatchTransformator {
}
}
- private void addContentTypeHeader(final ODataRequestBuilder requestBuilder, final Map<String, HeaderField> header) {
- String contentType = getContentTypeHeader(header);
-
- if (contentType != null) {
- requestBuilder.contentType(contentType);
- }
- }
-
- private String getContentTypeHeader(final Map<String, HeaderField> headers) {
- HeaderField contentTypeField = headers.get(HttpHeaders.CONTENT_TYPE.toLowerCase(Locale.ENGLISH));
- String contentType = null;
- if (contentTypeField != null) {
- for (String requestContentType : contentTypeField.getValues()) {
- contentType = contentType != null ? contentType + "," + requestContentType : requestContentType;
- }
- }
-
- return contentType;
- }
-
- private List<String> getAcceptHeaders(final Map<String, HeaderField> headers) {
- List<String> acceptHeaders = new ArrayList<String>();
- HeaderField requestAcceptHeaderField = headers.get(HttpHeaders.ACCEPT.toLowerCase(Locale.ENGLISH));
-
- if (requestAcceptHeaderField != null) {
- acceptHeaders = requestAcceptHeaderField.getValues();
- }
-
- return acceptHeaders;
- }
-
- private List<Locale> getAcceptLanguageHeaders(final Map<String, HeaderField> headers) {
- final HeaderField requestAcceptLanguageField = headers.get(HttpHeaders.ACCEPT_LANGUAGE.toLowerCase(Locale.ENGLISH));
+ private List<Locale> getAcceptLanguageHeaders(final Header headers) {
+ final List<String> acceptLanguageValues = headers.getHeaders(HttpHeaders.ACCEPT_LANGUAGE);
List<Locale> acceptLanguages = new ArrayList<Locale>();
- if (requestAcceptLanguageField != null) {
- for (String acceptLanguage : requestAcceptLanguageField.getValues()) {
- String[] part = acceptLanguage.split("-");
- String language = part[0];
- String country = "";
- if (part.length == 2) {
- country = part[part.length - 1];
- }
- Locale locale = new Locale(language, country);
- acceptLanguages.add(locale);
+ for (String acceptLanguage : acceptLanguageValues) {
+ String[] part = acceptLanguage.split("-");
+ String language = part[0];
+ String country = "";
+ if (part.length == 2) {
+ country = part[part.length - 1];
}
+ Locale locale = new Locale(language, country);
+ acceptLanguages.add(locale);
}
return acceptLanguages;
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/05d20c1f/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchResponseTransformator.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchResponseTransformator.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchResponseTransformator.java
index d82d09e..ab983ac 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchResponseTransformator.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchResponseTransformator.java
@@ -20,8 +20,6 @@ package org.apache.olingo.odata2.core.batch.v2;
import java.util.ArrayList;
import java.util.List;
-import java.util.Locale;
-import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -31,7 +29,6 @@ import org.apache.olingo.odata2.api.client.batch.BatchSingleResponse;
import org.apache.olingo.odata2.api.uri.PathInfo;
import org.apache.olingo.odata2.core.batch.BatchHelper;
import org.apache.olingo.odata2.core.batch.BatchSingleResponseImpl;
-import org.apache.olingo.odata2.core.batch.v2.BatchParserCommon.HeaderField;
public class BatchResponseTransformator implements BatchTransformator {
@@ -52,7 +49,6 @@ public class BatchResponseTransformator implements BatchTransformator {
List<BatchParserResult> resultList = new ArrayList<BatchParserResult>();
BatchTransformatorCommon.validateContentType(bodyPart.getHeaders());
-
resultList.addAll(handleBodyPart(bodyPart));
return resultList;
@@ -66,7 +62,9 @@ public class BatchResponseTransformator implements BatchTransformator {
bodyPartResult.add(transformChangeSet((BatchChangeSetPart) operation));
}
} else {
- bodyPartResult.add(transformQueryOperation(bodyPart.getRequests().get(0), getContentId(bodyPart.getHeaders())));
+ final String contentId = bodyPart.getHeaders().getHeader(BatchHelper.HTTP_CONTENT_ID);
+
+ bodyPartResult.add(transformQueryOperation(bodyPart.getRequests().get(0), contentId));
}
return bodyPartResult;
@@ -74,60 +72,53 @@ public class BatchResponseTransformator implements BatchTransformator {
private BatchSingleResponse transformChangeSet(final BatchChangeSetPart changeSet) throws BatchException {
BatchTransformatorCommon.validateContentTransferEncoding(changeSet.getHeaders(), true);
+ final String contentId = changeSet.getHeaders().getHeader(BatchHelper.HTTP_CONTENT_ID);
- return transformQueryOperation(changeSet.getRequest(), getContentId(changeSet.getHeaders()));
+ return transformQueryOperation(changeSet.getRequest(), contentId);
}
private BatchSingleResponse transformQueryOperation(final BatchQueryOperation operation, final String contentId)
throws BatchException {
+
+ final Matcher statusMatcher = prepareStatusLineMatcher(operation.getHttpStatusLine());
+
BatchSingleResponseImpl response = new BatchSingleResponseImpl();
response.setContentId(contentId);
- response.setHeaders(BatchParserCommon.headerFieldMapToSingleMap(operation.getHeaders()));
- response.setStatusCode(getStatusCode(operation.httpStatusLine));
- response.setStatusInfo(getStatusInfo(operation.getHttpStatusLine()));
+ response.setHeaders(operation.getHeaders().toSingleMap());
+ response.setStatusCode(getStatusCode(statusMatcher));
+ response.setStatusInfo(getStatusInfo(statusMatcher));
response.setBody(getBody(operation));
return response;
}
- private String getContentId(final Map<String, HeaderField> headers) {
- HeaderField contentIdField = headers.get(BatchHelper.HTTP_CONTENT_ID.toLowerCase(Locale.ENGLISH));
+ private Matcher prepareStatusLineMatcher(String httpStatusLine) throws BatchException {
+ final Pattern regexPattern = Pattern.compile(REG_EX_STATUS_LINE);
+ final Matcher matcher = regexPattern.matcher(httpStatusLine);
- if (contentIdField != null) {
- if (contentIdField.getValues().size() > 0) {
- return contentIdField.getValues().get(0);
- }
+ if (matcher.find()) {
+ return matcher;
+ } else {
+ throw new BatchException(BatchException.INVALID_STATUS_LINE);
}
-
- return null;
}
private String getBody(final BatchQueryOperation operation) throws BatchException {
int contentLength = BatchTransformatorCommon.getContentLength(operation.getHeaders());
- return BatchParserCommon.trimStringListToStringLength(operation.getBody(), contentLength);
- }
-
- private String getStatusCode(final String httpMethod) throws BatchException {
- Pattern regexPattern = Pattern.compile(REG_EX_STATUS_LINE);
- Matcher matcher = regexPattern.matcher(httpMethod);
-
- if (matcher.find()) {
- return matcher.group(1);
+ if (contentLength == -1) {
+ return BatchParserCommon.stringListToString(operation.getBody());
} else {
- throw new BatchException(BatchException.INVALID_STATUS_LINE);
+ return BatchParserCommon.trimStringListToStringLength(operation.getBody(), contentLength);
}
}
- private String getStatusInfo(final String httpMethod) throws BatchException {
- Pattern regexPattern = Pattern.compile(REG_EX_STATUS_LINE);
- Matcher matcher = regexPattern.matcher(httpMethod);
+ private String getStatusCode(final Matcher matcher) throws BatchException {
+ return matcher.group(1);
+ }
- if (matcher.find()) {
- return matcher.group(2);
- } else {
- throw new BatchException(BatchException.INVALID_STATUS_LINE);
- }
+ private String getStatusInfo(final Matcher matcher) throws BatchException {
+ return matcher.group(2);
}
}
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/05d20c1f/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchTransformatorCommon.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchTransformatorCommon.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchTransformatorCommon.java
index c9c8e0f..9c67f49 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchTransformatorCommon.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/BatchTransformatorCommon.java
@@ -1,49 +1,38 @@
package org.apache.olingo.odata2.core.batch.v2;
-import java.util.Locale;
-import java.util.Map;
+import java.util.List;
import org.apache.olingo.odata2.api.batch.BatchException;
import org.apache.olingo.odata2.api.commons.HttpContentType;
import org.apache.olingo.odata2.api.commons.HttpHeaders;
import org.apache.olingo.odata2.core.batch.BatchHelper;
-import org.apache.olingo.odata2.core.batch.v2.BatchParserCommon.HeaderField;
public class BatchTransformatorCommon {
- public static void validateContentType(final Map<String, HeaderField> headers) throws BatchException {
- final HeaderField contentTypeField = headers.get(HttpHeaders.CONTENT_TYPE.toLowerCase(Locale.ENGLISH));
- if (contentTypeField != null) {
- if (contentTypeField.getValues().size() == 1) {
- final String contentType = contentTypeField.getValues().get(0);
+ public static void validateContentType(final Header headers) throws BatchException {
+ List<String> contentTypes = headers.getHeaders(HttpHeaders.CONTENT_TYPE);
- if (!BatchParserCommon.PATTERN_MULTIPART_BOUNDARY.matcher(contentType).matches()
- && !BatchParserCommon.PATTERN_CONTENT_TYPE_APPLICATION_HTTP.matcher(contentType).matches()) {
- throw new BatchException(BatchException.INVALID_CONTENT_TYPE.addContent(HttpContentType.MULTIPART_MIXED
- + " or " + HttpContentType.APPLICATION_HTTP));
- }
- } else {
- throw new BatchException(BatchException.INVALID_HEADER);
- }
- } else {
+ if (contentTypes.size() == 0) {
throw new BatchException(BatchException.MISSING_CONTENT_TYPE);
}
+ if (!headers.isHeaderMatching(HttpHeaders.CONTENT_TYPE, BatchParserCommon.PATTERN_MULTIPART_BOUNDARY)
+ & !headers.isHeaderMatching(HttpHeaders.CONTENT_TYPE, BatchParserCommon.PATTERN_CONTENT_TYPE_APPLICATION_HTTP)) {
+ throw new BatchException(BatchException.INVALID_CONTENT_TYPE.addContent(
+ HttpContentType.MULTIPART_MIXED + " or " + HttpContentType.APPLICATION_HTTP));
+ }
}
- public static void validateContentTransferEncoding(final Map<String, HeaderField> headers,
- final boolean isChangeRequest)
+ public static void validateContentTransferEncoding(final Header headers, final boolean isChangeRequest)
throws BatchException {
- if (headers.containsKey(BatchHelper.HTTP_CONTENT_TRANSFER_ENCODING.toLowerCase(Locale.ENGLISH))) {
- HeaderField encodingField = headers.get(BatchHelper.HTTP_CONTENT_TRANSFER_ENCODING.toLowerCase(Locale.ENGLISH));
+ final List<String> contentTransferEncodings = headers.getHeaders(BatchHelper.HTTP_CONTENT_TRANSFER_ENCODING);
- if (encodingField.getValues().size() == 1) {
- String encoding = encodingField.getValues().get(0);
+ if (contentTransferEncodings.size() != 0) {
+ if (contentTransferEncodings.size() == 1) {
+ String encoding = contentTransferEncodings.get(0);
if (!BatchHelper.BINARY_ENCODING.equalsIgnoreCase(encoding)) {
throw new BatchException(BatchException.INVALID_CONTENT_TRANSFER_ENCODING);
}
- } else if (encodingField.getValues().size() == 0) {
- throw new BatchException(BatchException.INVALID_CONTENT_TRANSFER_ENCODING);
} else {
throw new BatchException(BatchException.INVALID_HEADER);
}
@@ -54,12 +43,12 @@ public class BatchTransformatorCommon {
}
}
- public static int getContentLength(final Map<String, HeaderField> headers) throws BatchException {
+ public static int getContentLength(final Header headers) throws BatchException {
+ final List<String> contentLengths = headers.getHeaders(HttpHeaders.CONTENT_LENGTH);
- if (headers.containsKey(HttpHeaders.CONTENT_LENGTH.toLowerCase(Locale.ENGLISH))) {
+ if (contentLengths.size() == 1) {
try {
- int contentLength =
- Integer.parseInt(headers.get(HttpHeaders.CONTENT_LENGTH.toLowerCase(Locale.ENGLISH)).getValues().get(0));
+ int contentLength = Integer.parseInt(contentLengths.get(0));
if (contentLength < 0) {
throw new BatchException(BatchException.INVALID_HEADER);
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/05d20c1f/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/Header.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/Header.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/Header.java
new file mode 100644
index 0000000..7901b7b
--- /dev/null
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/v2/Header.java
@@ -0,0 +1,202 @@
+package org.apache.olingo.odata2.core.batch.v2;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+public class Header implements Cloneable {
+
+ private final Map<String, HeaderField> headers = new HashMap<String, HeaderField>();
+
+ public static List<String> splitValuesByComma(final String headerValue) {
+ final List<String> singleValues = new ArrayList<String>();
+
+ String[] parts = headerValue.split(",");
+ for (final String value : parts) {
+ singleValues.add(value.trim());
+ }
+
+ return singleValues;
+ }
+
+ public void addHeader(final String name, final String value) {
+ final HeaderField headerField = getHeaderFieldOrDefault(name);
+ final List<String> headerValues = headerField.getValues();
+
+ if (!headerValues.contains(value)) {
+ headerValues.add(value);
+ }
+ }
+
+ public void addHeader(final String name, final List<String> values) {
+ final HeaderField headerField = getHeaderFieldOrDefault(name);
+ final List<String> headerValues = headerField.getValues();
+
+ for (final String value : values) {
+ if (!headerValues.contains(value)) {
+ headerValues.add(value);
+ }
+ }
+ }
+
+ public boolean isHeaderMatching(final String name, final Pattern pattern) {
+ if(getHeaders(name).size() != 1 ) {
+ return false;
+ } else {
+ return pattern.matcher(getHeaders(name).get(0)).matches();
+ }
+ }
+
+ public void removeHeaders(final String name) {
+ headers.remove(name.toLowerCase(Locale.ENGLISH));
+ }
+
+ public String getHeader(final String name) {
+ final HeaderField headerField = getHeaderField(name);
+
+ if (headerField == null) {
+ return null;
+ } else {
+ final List<String> headerValues = headerField.getValues();
+ final StringBuilder result = new StringBuilder();
+
+ for (final String value : headerValues) {
+ result.append(value);
+ result.append(", ");
+ }
+
+ if(result.length()>0) {
+ result.delete(result.length() - 2, result.length());
+ }
+
+ return result.toString();
+ }
+ }
+
+ public String getHeaderNotNull(final String name) {
+ final String value = getHeader(name);
+
+ return (value == null) ? "" : value;
+ }
+
+ public List<String> getHeaders(final String name) {
+ final HeaderField headerField = getHeaderField(name);
+
+ return (headerField == null) ? new ArrayList<String>() : headerField.getValues();
+ }
+
+ public HeaderField getHeaderField(final String name) {
+ return headers.get(name.toLowerCase(Locale.ENGLISH));
+ }
+
+ public Map<String, String> toSingleMap() {
+ final Map<String, String> singleMap = new HashMap<String, String>();
+
+ for (final String key : headers.keySet()) {
+ HeaderField field = headers.get(key);
+ singleMap.put(field.getFieldName(), getHeader(key));
+ }
+
+ return singleMap;
+ }
+
+ public Map<String, List<String>> toMultiMap() {
+ final Map<String, List<String>> singleMap = new HashMap<String, List<String>>();
+
+ for (final String key : headers.keySet()) {
+ HeaderField field = headers.get(key);
+ singleMap.put(field.getFieldName(), field.getValues());
+ }
+
+ return singleMap;
+ }
+
+ private HeaderField getHeaderFieldOrDefault(final String name) {
+ HeaderField headerField = headers.get(name.toLowerCase(Locale.ENGLISH));
+
+ if (headerField == null) {
+ headerField = new HeaderField(name);
+ headers.put(name.toLowerCase(Locale.ENGLISH), headerField);
+ }
+
+ return headerField;
+ }
+
+ @Override
+ public Header clone() {
+ final Header newInstance = new Header();
+
+ for (final String key : headers.keySet()) {
+ newInstance.headers.put(key, headers.get(key).clone());
+ }
+
+ return newInstance;
+ }
+
+ public static class HeaderField implements Cloneable {
+ private String fieldName;
+ private List<String> values;
+
+ public HeaderField(final String fieldName) {
+ this(fieldName, new ArrayList<String>());
+ }
+
+ public HeaderField(final String fieldName, final List<String> values) {
+ this.fieldName = fieldName;
+ this.values = values;
+ }
+
+ public String getFieldName() {
+ return fieldName;
+ }
+
+ public List<String> getValues() {
+ return values;
+ }
+
+ public void setValues(final List<String> values) {
+ this.values = values;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((fieldName == null) ? 0 : fieldName.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ HeaderField other = (HeaderField) obj;
+ if (fieldName == null) {
+ if (other.fieldName != null) {
+ return false;
+ }
+ } else if (!fieldName.equals(other.fieldName)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public HeaderField clone() {
+ List<String> newValues = new ArrayList<String>();
+ newValues.addAll(values);
+
+ return new HeaderField(fieldName, newValues);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/05d20c1f/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchParserCommonTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchParserCommonTest.java b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchParserCommonTest.java
index 8451c55..56cbeeb 100644
--- a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchParserCommonTest.java
+++ b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchParserCommonTest.java
@@ -5,13 +5,11 @@ import static org.junit.Assert.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import java.util.Locale;
-import java.util.Map;
import org.apache.olingo.odata2.api.batch.BatchException;
import org.apache.olingo.odata2.api.commons.HttpHeaders;
import org.apache.olingo.odata2.core.batch.v2.BatchParserCommon;
-import org.apache.olingo.odata2.core.batch.v2.BatchParserCommon.HeaderField;
+import org.apache.olingo.odata2.core.batch.v2.Header;
import org.junit.Test;
public class BatchParserCommonTest {
@@ -30,14 +28,14 @@ public class BatchParserCommonTest {
message.addAll(Arrays.asList(messageRaw));
- final Map<String, HeaderField> header = BatchParserCommon.consumeHeaders(message);
+ final Header header = BatchParserCommon.consumeHeaders(message);
assertNotNull(header);
- final HeaderField contentIdHeaders = header.get(BatchHelper.HTTP_CONTENT_ID.toLowerCase(Locale.ENGLISH));
+ final List<String> contentIdHeaders = header.getHeaders(BatchHelper.HTTP_CONTENT_ID);
assertNotNull(contentIdHeaders);
- assertEquals(2, contentIdHeaders.getValues().size());
- assertEquals("1", contentIdHeaders.getValues().get(0));
- assertEquals("2", contentIdHeaders.getValues().get(1));
+ assertEquals(2, contentIdHeaders.size());
+ assertEquals("1", contentIdHeaders.get(0));
+ assertEquals("2", contentIdHeaders.get(1));
}
@Test
@@ -52,13 +50,13 @@ public class BatchParserCommonTest {
message.addAll(Arrays.asList(messageRaw));
- final Map<String, HeaderField> header = BatchParserCommon.consumeHeaders(message);
+ final Header header = BatchParserCommon.consumeHeaders(message);
assertNotNull(header);
- final HeaderField contentIdHeaders = header.get(BatchHelper.HTTP_CONTENT_ID.toLowerCase(Locale.ENGLISH));
+ final List<String> contentIdHeaders = header.getHeaders(BatchHelper.HTTP_CONTENT_ID);
assertNotNull(contentIdHeaders);
- assertEquals(1, contentIdHeaders.getValues().size());
- assertEquals("1", contentIdHeaders.getValues().get(0));
+ assertEquals(1, contentIdHeaders.size());
+ assertEquals("1", contentIdHeaders.get(0));
}
@Test
@@ -73,16 +71,16 @@ public class BatchParserCommonTest {
message.addAll(Arrays.asList(messageRaw));
- final Map<String, HeaderField> header = BatchParserCommon.consumeHeaders(message);
+ final Header header = BatchParserCommon.consumeHeaders(message);
assertNotNull(header);
- final HeaderField upgradeHeader = header.get("upgrade");
+ final List<String> upgradeHeader = header.getHeaders("upgrade");
assertNotNull(upgradeHeader);
- assertEquals(4, upgradeHeader.getValues().size());
- assertEquals("HTTP/2.0", upgradeHeader.getValues().get(0));
- assertEquals("SHTTP/1.3", upgradeHeader.getValues().get(1));
- assertEquals("IRC/6.9", upgradeHeader.getValues().get(2));
- assertEquals("RTA/x11", upgradeHeader.getValues().get(3));
+ assertEquals(4, upgradeHeader.size());
+ assertEquals("HTTP/2.0", upgradeHeader.get(0));
+ assertEquals("SHTTP/1.3", upgradeHeader.get(1));
+ assertEquals("IRC/6.9", upgradeHeader.get(2));
+ assertEquals("RTA/x11", upgradeHeader.get(3));
}
@Test
@@ -98,12 +96,12 @@ public class BatchParserCommonTest {
message.addAll(Arrays.asList(messageRaw));
- final Map<String, HeaderField> header = BatchParserCommon.consumeHeaders(message);
+ final Header header = BatchParserCommon.consumeHeaders(message);
assertNotNull(header);
- final HeaderField acceptHeader = header.get(HttpHeaders.ACCEPT.toLowerCase());
+ final List<String> acceptHeader = header.getHeaders(HttpHeaders.ACCEPT);
assertNotNull(acceptHeader);
- assertEquals(4, acceptHeader.getValues().size());
+ assertEquals(4, acceptHeader.size());
}
@Test
@@ -119,12 +117,12 @@ public class BatchParserCommonTest {
message.addAll(Arrays.asList(messageRaw));
- final Map<String, HeaderField> header = BatchParserCommon.consumeHeaders(message);
+ final Header header = BatchParserCommon.consumeHeaders(message);
assertNotNull(header);
- final HeaderField acceptHeader = header.get(HttpHeaders.ACCEPT.toLowerCase());
+ final List<String> acceptHeader = header.getHeaders(HttpHeaders.ACCEPT);
assertNotNull(acceptHeader);
- assertEquals(3, acceptHeader.getValues().size());
+ assertEquals(3, acceptHeader.size());
}
@Test
@@ -138,12 +136,12 @@ public class BatchParserCommonTest {
List<String> message = new ArrayList<String>();
message.addAll(Arrays.asList(messageRaw));
- final Map<String, HeaderField> header = BatchParserCommon.consumeHeaders(message);
+ final Header header = BatchParserCommon.consumeHeaders(message);
assertNotNull(header);
- final HeaderField acceptLanguageHeader = header.get(HttpHeaders.ACCEPT_LANGUAGE.toLowerCase());
+ final List<String> acceptLanguageHeader = header.getHeaders(HttpHeaders.ACCEPT_LANGUAGE);
assertNotNull(acceptLanguageHeader);
- assertEquals(4, acceptLanguageHeader.getValues().size());
+ assertEquals(4, acceptLanguageHeader.size());
}
@Test
@@ -157,12 +155,12 @@ public class BatchParserCommonTest {
List<String> message = new ArrayList<String>();
message.addAll(Arrays.asList(messageRaw));
- final Map<String, HeaderField> header = BatchParserCommon.consumeHeaders(message);
+ final Header header = BatchParserCommon.consumeHeaders(message);
assertNotNull(header);
- final HeaderField acceptLanguageHeader = header.get(HttpHeaders.ACCEPT_LANGUAGE.toLowerCase());
+ final List<String> acceptLanguageHeader = header.getHeaders(HttpHeaders.ACCEPT_LANGUAGE);
assertNotNull(acceptLanguageHeader);
- assertEquals(3, acceptLanguageHeader.getValues().size());
+ assertEquals(3, acceptLanguageHeader.size());
}
@Test
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/05d20c1f/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchTransformatorCommonTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchTransformatorCommonTest.java b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchTransformatorCommonTest.java
index a70d15a..e98a295 100644
--- a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchTransformatorCommonTest.java
+++ b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchTransformatorCommonTest.java
@@ -1,15 +1,13 @@
package org.apache.olingo.odata2.core.batch;
import java.util.Arrays;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import org.apache.olingo.odata2.api.batch.BatchException;
import org.apache.olingo.odata2.api.commons.HttpContentType;
import org.apache.olingo.odata2.api.commons.HttpHeaders;
-import org.apache.olingo.odata2.core.batch.v2.BatchParserCommon.HeaderField;
import org.apache.olingo.odata2.core.batch.v2.BatchTransformatorCommon;
+import org.apache.olingo.odata2.core.batch.v2.Header;
import org.junit.Test;
public class BatchTransformatorCommonTest {
@@ -19,7 +17,7 @@ public class BatchTransformatorCommonTest {
@Test
public void testValidateContentTypeApplicationHTTP() throws BatchException {
List<String> contentTypeValues = Arrays.asList(new String[] { HttpContentType.APPLICATION_HTTP });
- Map<String, HeaderField> headers = makeHeaders(HttpHeaders.CONTENT_TYPE, contentTypeValues);
+ final Header headers = makeHeaders(HttpHeaders.CONTENT_TYPE, contentTypeValues);
BatchTransformatorCommon.validateContentType(headers);
}
@@ -28,7 +26,7 @@ public class BatchTransformatorCommonTest {
public void testValidateContentTypeMultipartMixed() throws BatchException {
List<String> contentTypeValues =
Arrays.asList(new String[] { HttpContentType.MULTIPART_MIXED + "; boundary=batch_32332_32323_fdsf" });
- Map<String, HeaderField> headers = makeHeaders(HttpHeaders.CONTENT_TYPE, contentTypeValues);
+ final Header headers = makeHeaders(HttpHeaders.CONTENT_TYPE, contentTypeValues);
BatchTransformatorCommon.validateContentType(headers);
}
@@ -37,7 +35,7 @@ public class BatchTransformatorCommonTest {
public void testValidateContentTypeMultipartMixedCaseInsensitiv() throws BatchException {
List<String> contentTypeValues =
Arrays.asList(new String[] { "mulTiPart/MiXed; boundary=batch_32332_32323_fdsf" });
- Map<String, HeaderField> headers = makeHeaders(HttpHeaders.CONTENT_TYPE, contentTypeValues);
+ final Header headers = makeHeaders(HttpHeaders.CONTENT_TYPE, contentTypeValues);
BatchTransformatorCommon.validateContentType(headers);
}
@@ -45,14 +43,15 @@ public class BatchTransformatorCommonTest {
@Test(expected = BatchException.class)
public void testValidateContentTypeNoValue() throws BatchException {
List<String> contentTypeValues = Arrays.asList(new String[] {});
- Map<String, HeaderField> headers = makeHeaders(HttpHeaders.CONTENT_TYPE, contentTypeValues);
+ final Header headers = makeHeaders(HttpHeaders.CONTENT_TYPE, contentTypeValues);
BatchTransformatorCommon.validateContentType(headers);
}
@Test(expected = BatchException.class)
public void testValidateContentTypeMissingHeader() throws BatchException {
- Map<String, HeaderField> headers = new HashMap<String, HeaderField>();
+ final Header headers = new Header();
+
BatchTransformatorCommon.validateContentType(headers);
}
@@ -60,7 +59,7 @@ public class BatchTransformatorCommonTest {
public void testValidateContentTypeMultipleValues() throws BatchException {
List<String> contentTypeValues =
Arrays.asList(new String[] { HttpContentType.APPLICATION_HTTP, HttpContentType.MULTIPART_MIXED });
- Map<String, HeaderField> headers = makeHeaders(HttpHeaders.CONTENT_TYPE, contentTypeValues);
+ final Header headers = makeHeaders(HttpHeaders.CONTENT_TYPE, contentTypeValues);
BatchTransformatorCommon.validateContentType(headers);
}
@@ -68,7 +67,7 @@ public class BatchTransformatorCommonTest {
@Test
public void testValidateContentTransferEncoding() throws BatchException {
List<String> contentTransferEncoding = Arrays.asList(new String[] { BatchHelper.BINARY_ENCODING });
- Map<String, HeaderField> headers = makeHeaders(BatchHelper.HTTP_CONTENT_TRANSFER_ENCODING, contentTransferEncoding);
+ final Header headers = makeHeaders(BatchHelper.HTTP_CONTENT_TRANSFER_ENCODING, contentTransferEncoding);
BatchTransformatorCommon.validateContentTransferEncoding(headers, false);
}
@@ -76,28 +75,29 @@ public class BatchTransformatorCommonTest {
@Test(expected = BatchException.class)
public void testValidateContentTransferEncodingMultipleValues() throws BatchException {
List<String> contentTransferEncoding = Arrays.asList(new String[] { BatchHelper.BINARY_ENCODING, BASE64_ENCODING });
- Map<String, HeaderField> headers = makeHeaders(BatchHelper.HTTP_CONTENT_TRANSFER_ENCODING, contentTransferEncoding);
+ final Header headers = makeHeaders(BatchHelper.HTTP_CONTENT_TRANSFER_ENCODING, contentTransferEncoding);
BatchTransformatorCommon.validateContentTransferEncoding(headers, false);
}
@Test(expected = BatchException.class)
public void testValidateContentTransferEncodingMissingHeader() throws BatchException {
- Map<String, HeaderField> headers = new HashMap<String, HeaderField>();
+ final Header headers = new Header();
+
BatchTransformatorCommon.validateContentTransferEncoding(headers, true);
}
@Test(expected = BatchException.class)
public void testValidateContentTransferEncodingMissingValue() throws BatchException {
List<String> contentTransferEncoding = Arrays.asList(new String[] {});
- Map<String, HeaderField> headers = makeHeaders(BatchHelper.HTTP_CONTENT_TRANSFER_ENCODING, contentTransferEncoding);
+ final Header headers = makeHeaders(BatchHelper.HTTP_CONTENT_TRANSFER_ENCODING, contentTransferEncoding);
- BatchTransformatorCommon.validateContentTransferEncoding(headers, false);
+ BatchTransformatorCommon.validateContentTransferEncoding(headers, true);
}
- private Map<String, HeaderField> makeHeaders(final String headerName, final List<String> values) {
- Map<String, HeaderField> headers = new HashMap<String, HeaderField>();
- headers.put(headerName.toLowerCase(), new HeaderField(headerName, values));
+ private Header makeHeaders(final String headerName, final List<String> values) {
+ final Header headers = new Header();
+ headers.addHeader(headerName, values);
return headers;
}
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/05d20c1f/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/HeaderTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/HeaderTest.java b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/HeaderTest.java
new file mode 100644
index 0000000..128aa2e
--- /dev/null
+++ b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/HeaderTest.java
@@ -0,0 +1,161 @@
+package org.apache.olingo.odata2.core.batch;
+
+import static org.junit.Assert.*;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.commons.HttpContentType;
+import org.apache.olingo.odata2.api.commons.HttpHeaders;
+import org.apache.olingo.odata2.core.batch.v2.BatchParserCommon;
+import org.apache.olingo.odata2.core.batch.v2.Header;
+import org.junit.Test;
+
+public class HeaderTest {
+
+ @Test
+ public void test() {
+ Header header = new Header();
+ header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED);
+
+ assertEquals(HttpContentType.MULTIPART_MIXED, header.getHeader(HttpHeaders.CONTENT_TYPE));
+ assertEquals(1, header.getHeaders(HttpHeaders.CONTENT_TYPE).size());
+ assertEquals(HttpContentType.MULTIPART_MIXED, header.getHeaders(HttpHeaders.CONTENT_TYPE).get(0));
+ }
+
+ @Test
+ public void testNotAvailable() {
+ Header header = new Header();
+
+ assertNull(header.getHeader(HttpHeaders.CONTENT_TYPE));
+ assertEquals(0, header.getHeaders(HttpHeaders.CONTENT_TYPE).size());
+ assertEquals("", header.getHeaderNotNull(HttpHeaders.CONTENT_TYPE));
+ }
+
+ @Test
+ public void testCaseInsensitive() {
+ Header header = new Header();
+ header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED);
+
+ assertEquals(HttpContentType.MULTIPART_MIXED, header.getHeader("cOnTenT-TyPE"));
+ assertEquals(1, header.getHeaders("cOnTenT-TyPE").size());
+ assertEquals(HttpContentType.MULTIPART_MIXED, header.getHeaders("cOnTenT-TyPE").get(0));
+ }
+
+ @Test
+ public void testDuplicatedAdd() {
+ Header header = new Header();
+ header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED);
+ header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED);
+
+ assertEquals(HttpContentType.MULTIPART_MIXED, header.getHeader(HttpHeaders.CONTENT_TYPE));
+ assertEquals(1, header.getHeaders(HttpHeaders.CONTENT_TYPE).size());
+ assertEquals(HttpContentType.MULTIPART_MIXED, header.getHeaders(HttpHeaders.CONTENT_TYPE).get(0));
+ }
+
+ @Test
+ public void testMatcher() {
+ Header header = new Header();
+ header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED + ";boundary=123");
+
+ assertTrue(header.isHeaderMatching(HttpHeaders.CONTENT_TYPE, BatchParserCommon.PATTERN_MULTIPART_BOUNDARY));
+ }
+
+ @Test
+ public void testFieldName() {
+ Header header = new Header();
+ header.addHeader("MyFieldNamE", "myValue");
+
+ assertEquals("MyFieldNamE", header.getHeaderField("myfieldname").getFieldName());
+ assertEquals("MyFieldNamE", header.toSingleMap().keySet().toArray(new String[0])[0]);
+ assertEquals("MyFieldNamE", header.toMultiMap().keySet().toArray(new String[0])[0]);
+
+ assertEquals("myValue", header.toMultiMap().get("MyFieldNamE").get(0));
+ assertEquals("myValue", header.toSingleMap().get("MyFieldNamE"));
+ }
+
+ @Test
+ public void testDeepCopy() {
+ Header header = new Header();
+ header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED + ";boundary=123");
+
+ Header copy = header.clone();
+ assertEquals(header.getHeaders(HttpHeaders.CONTENT_TYPE), copy.getHeaders(HttpHeaders.CONTENT_TYPE));
+ assertEquals(header.getHeader(HttpHeaders.CONTENT_TYPE), copy.getHeader(HttpHeaders.CONTENT_TYPE));
+ assertEquals(header.getHeaderField(HttpHeaders.CONTENT_TYPE), copy.getHeaderField(HttpHeaders.CONTENT_TYPE));
+
+ assertTrue(header.getHeaders(HttpHeaders.CONTENT_TYPE) != copy.getHeaders(HttpHeaders.CONTENT_TYPE));
+ assertTrue(header.getHeaderField(HttpHeaders.CONTENT_TYPE) != copy.getHeaderField(HttpHeaders.CONTENT_TYPE));
+ }
+
+ @Test
+ public void testMatcherNoHeader() {
+ Header header = new Header();
+
+ assertFalse(header.isHeaderMatching(HttpHeaders.CONTENT_TYPE, BatchParserCommon.PATTERN_MULTIPART_BOUNDARY));
+ }
+
+ @Test
+ public void testMatcherFail() {
+ Header header = new Header();
+ header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED + ";boundary=123");
+
+ assertFalse(header.isHeaderMatching(HttpHeaders.CONTENT_TYPE, BatchParserCommon.PATTERN_HEADER_LINE));
+ }
+
+ @Test
+ public void testDuplicatedAddList() {
+ Header header = new Header();
+ header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED);
+ header.addHeader(HttpHeaders.CONTENT_TYPE, Arrays.asList(new String[] { HttpContentType.MULTIPART_MIXED,
+ HttpContentType.APPLICATION_ATOM_SVC }));
+
+ assertEquals(HttpContentType.MULTIPART_MIXED + ", " + HttpContentType.APPLICATION_ATOM_SVC, header
+ .getHeader(HttpHeaders.CONTENT_TYPE));
+ assertEquals(2, header.getHeaders(HttpHeaders.CONTENT_TYPE).size());
+ assertEquals(HttpContentType.MULTIPART_MIXED, header.getHeaders(HttpHeaders.CONTENT_TYPE).get(0));
+ assertEquals(HttpContentType.APPLICATION_ATOM_SVC, header.getHeaders(HttpHeaders.CONTENT_TYPE).get(1));
+ }
+
+ @Test
+ public void testRemove() {
+ Header header = new Header();
+ header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED);
+ header.removeHeaders(HttpHeaders.CONTENT_TYPE);
+
+ assertNull(header.getHeader(HttpHeaders.CONTENT_TYPE));
+ assertEquals(0, header.getHeaders(HttpHeaders.CONTENT_TYPE).size());
+ }
+
+ @Test
+ public void testMultipleValues() {
+ Header header = new Header();
+ header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED);
+ header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.APPLICATION_ATOM_SVC);
+ header.addHeader(HttpHeaders.CONTENT_TYPE, HttpContentType.APPLICATION_ATOM_XML);
+
+ final String fullHeaderString =
+ HttpContentType.MULTIPART_MIXED + ", " + HttpContentType.APPLICATION_ATOM_SVC + ", "
+ + HttpContentType.APPLICATION_ATOM_XML;
+
+ assertEquals(fullHeaderString, header.getHeader(HttpHeaders.CONTENT_TYPE));
+ assertEquals(3, header.getHeaders(HttpHeaders.CONTENT_TYPE).size());
+ assertEquals(HttpContentType.MULTIPART_MIXED, header.getHeaders(HttpHeaders.CONTENT_TYPE).get(0));
+ assertEquals(HttpContentType.APPLICATION_ATOM_SVC, header.getHeaders(HttpHeaders.CONTENT_TYPE).get(1));
+ assertEquals(HttpContentType.APPLICATION_ATOM_XML, header.getHeaders(HttpHeaders.CONTENT_TYPE).get(2));
+ }
+
+ @Test
+ public void testSplitValues() {
+ final String values = "abc, def,123,77, 99, ysd";
+ List<String> splittedValues = Header.splitValuesByComma(values);
+
+ assertEquals(6, splittedValues.size());
+ assertEquals("abc", splittedValues.get(0));
+ assertEquals("def", splittedValues.get(1));
+ assertEquals("123", splittedValues.get(2));
+ assertEquals("77", splittedValues.get(3));
+ assertEquals("99", splittedValues.get(4));
+ assertEquals("ysd", splittedValues.get(5));
+ }
+}
[3/4] Line number tracking and exception messages
Posted by ch...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/f0dc0f74/odata2-lib/odata-core/src/test/resources/batchLarge.batch
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/test/resources/batchLarge.batch b/odata2-lib/odata-core/src/test/resources/batchLarge.batch
new file mode 100644
index 0000000..3be0982
--- /dev/null
+++ b/odata2-lib/odata-core/src/test/resources/batchLarge.batch
@@ -0,0 +1,2505 @@
+--batch_8194-cf13-1f56
+Content-Type: application/http
+Content-Transfer-Encoding: binary
+
+GET Employees HTTP/1.1
+Host: http://localhost/odata
+Connection: keep-alive
+Authorization: Basic YW56ZWlnZXI6ZGlzcGxheQ==
+Accept: application/atom+xml
+MaxDataServiceVersion: 2.0
+X-CSRF-Token: P6no0PBwygp1ie0Gz-YbEg==
+DataServiceVersion: 2.0
+User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36
+Content-Type: application/atom+xml
+Accept-Encoding: gzip,deflate
+Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
+
+
+--batch_8194-cf13-1f56
+Content-Type: application/http
+Content-Transfer-Encoding: binary
+
+GET Employees HTTP/1.1
+Host: http://localhost/odata
+Connection: keep-alive
+Authorization: Basic YW56ZWlnZXI6ZGlzcGxheQ==
+Accept: application/atom+xml
+MaxDataServiceVersion: 2.0
+X-CSRF-Token: P6no0PBwygp1ie0Gz-YbEg==
+DataServiceVersion: 2.0
+User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36
+Content-Type: application/atom+xml
+Accept-Encoding: gzip,deflate
+Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
+
+
+--batch_8194-cf13-1f56
+Content-Type: application/http
+Content-Transfer-Encoding: binary
+
+GET Employees HTTP/1.1
+Host: http://localhost/odata
+Connection: keep-alive
+Authorization: Basic YW56ZWlnZXI6ZGlzcGxheQ==
+Accept: application/atom+xml
+MaxDataServiceVersion: 2.0
+X-CSRF-Token: P6no0PBwygp1ie0Gz-YbEg==
+DataServiceVersion: 2.0
+User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36
+Content-Type: application/atom+xml
+Accept-Encoding: gzip,deflate
+Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
+
+
+--batch_8194-cf13-1f56
+Content-Type: multipart/mixed; boundary=changeset_f980-1cb6-94dd
+
+--changeset_f980-1cb6-94dd
+Content-Type: application/http
+Content-Transfer-Encoding: binary
+Content-ID: 1
+
+POST Employees HTTP/1.1
+Host: http://localhost/odata
+Connection: keep-alive
+Content-Length: 1117
+Authorization: Basic YW56ZWlnZXI6ZGlzcGxheQ==
+Origin: chrome-extension://hgmloofddffdnphfgcellkdfbfbjeloo
+X-CSRF-Token: P6no0PBwygp1ie0Gz-YbEg==
+User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36
+Content-Type: application/atom+xml
+Accept: */*
+Accept-Encoding: gzip,deflate
+Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
+
+<entry xmlns="http://www.w3.org/2005/Atom"
+ xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
+ xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
+ xml:base="http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/"
+ m:etag="W/2">
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Rooms('2')
+ </id>
+ <title type="text">Room 2</title>
+ <updated>2013-04-03T10:53:26.021+02:00</updated>
+ <category term="RefScenario.Room"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Rooms('2')" rel="edit" title="Room" />
+ <link href="Rooms('2')/nr_Employees"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/nr_Employees"
+ title="nr_Employees" type="application/atom+xml; type=feed">
+ <m:inline>
+ <feed xmlns="http://www.w3.org/2005/Atom"
+ xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
+ xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
+ xml:base="http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/">
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees
+ </id>
+ <title type="text">Employees</title>
+ <updated>2013-04-03T10:53:26.024+02:00</updated>
+ <author>
+ <name />
+ </author>
+ <link href="Employees" rel="self" title="Employees" />
+ <entry>
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees('2')
+ </id>
+ <title type="text">Frederic Fall</title>
+ <updated>2003-07-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('2')" rel="edit" title="Employee" />
+ <link href="Employees('2')/$value" rel="edit-media"
+ type="application/octet-stream" />
+ <link href="Employees('2')/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+ title="ne_Manager" type="application/atom+xml; type=entry" />
+ <link href="Employees('2')/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+ title="ne_Team" type="application/atom+xml; type=entry" />
+ <link href="Employees('2')/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+ title="ne_Room" type="application/atom+xml; type=entry" />
+ <content type="application/octet-stream" src="Employees('2')/$value" />
+ <m:properties>
+ <d:EmployeeId>2</d:EmployeeId>
+ <d:EmployeeName>Frederic Fall</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>2</d:RoomId>
+ <d:TeamId>1</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69190</d:PostalCode>
+ <d:CityName>Walldorf</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>32</d:Age>
+ <d:EntryDate>2003-07-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('2')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees('3')
+ </id>
+ <title type="text">Jonathan Smith</title>
+ <updated>2013-04-03T10:53:26.025+02:00</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('3')" rel="edit" title="Employee" />
+ <link href="Employees('3')/$value" rel="edit-media"
+ type="application/octet-stream" />
+ <link href="Employees('3')/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+ title="ne_Manager" type="application/atom+xml; type=entry" />
+ <link href="Employees('3')/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+ title="ne_Team" type="application/atom+xml; type=entry" />
+ <link href="Employees('3')/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+ title="ne_Room" type="application/atom+xml; type=entry" />
+ <content type="application/octet-stream" src="Employees('3')/$value" />
+ <m:properties>
+ <d:EmployeeId>3</d:EmployeeId>
+ <d:EmployeeName>Jonathan Smith</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>2</d:RoomId>
+ <d:TeamId>1</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69190</d:PostalCode>
+ <d:CityName>Walldorf</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>56</d:Age>
+ <d:EntryDate m:null="true" />
+ <d:ImageUrl>Employees('3')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees('4')
+ </id>
+ <title type="text">Peter Burke</title>
+ <updated>2004-09-12T00:00:00Z</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('4')" rel="edit" title="Employee" />
+ <link href="Employees('4')/$value" rel="edit-media"
+ type="application/octet-stream" />
+ <link href="Employees('4')/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+ title="ne_Manager" type="application/atom+xml; type=entry" />
+ <link href="Employees('4')/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+ title="ne_Team" type="application/atom+xml; type=entry" />
+ <link href="Employees('4')/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+ title="ne_Room" type="application/atom+xml; type=entry" />
+ <content type="application/octet-stream" src="Employees('4')/$value" />
+ <m:properties>
+ <d:EmployeeId>4</d:EmployeeId>
+ <d:EmployeeName>Peter Burke</d:EmployeeName>
+ <d:ManagerId>3</d:ManagerId>
+ <d:RoomId>2</d:RoomId>
+ <d:TeamId>2</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69190</d:PostalCode>
+ <d:CityName>Walldorf</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>39</d:Age>
+ <d:EntryDate>2004-09-12T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('4')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees('6')
+ </id>
+ <title type="text">Susan Bay</title>
+ <updated>2010-12-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('6')" rel="edit" title="Employee" />
+ <link href="Employees('6')/$value" rel="edit-media"
+ type="application/octet-stream" />
+ <link href="Employees('6')/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+ title="ne_Manager" type="application/atom+xml; type=entry" />
+ <link href="Employees('6')/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+ title="ne_Team" type="application/atom+xml; type=entry" />
+ <link href="Employees('6')/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+ title="ne_Room" type="application/atom+xml; type=entry" />
+ <content type="application/octet-stream" src="Employees('6')/$value" />
+ <m:properties>
+ <d:EmployeeId>6</d:EmployeeId>
+ <d:EmployeeName>Susan Bay</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>2</d:RoomId>
+ <d:TeamId>3</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69190</d:PostalCode>
+ <d:CityName>Walldorf</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>29</d:Age>
+ <d:EntryDate>2010-12-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('6')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ </feed>
+ </m:inline>
+ </link>
+ <link href="Rooms('2')/nr_Building"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/nr_Building"
+ title="nr_Building" type="application/atom+xml; type=entry" />
+ <content type="application/xml">
+ <m:properties>
+ <d:Id>2</d:Id>
+ <d:Name>Room 2</d:Name>
+ <d:Seats>5</d:Seats>
+ <d:Version>2</d:Version>
+ </m:properties>
+ </content>
+</entry>
+
+--changeset_f980-1cb6-94dd
+Content-Type: application/http
+Content-Transfer-Encoding: binary
+Content-ID: 1
+
+POST Employees HTTP/1.1
+Host: http://localhost/odata
+Connection: keep-alive
+Content-Length: 1117
+Authorization: Basic YW56ZWlnZXI6ZGlzcGxheQ==
+Origin: chrome-extension://hgmloofddffdnphfgcellkdfbfbjeloo
+X-CSRF-Token: P6no0PBwygp1ie0Gz-YbEg==
+User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36
+Content-Type: application/atom+xml
+Accept: */*
+Accept-Encoding: gzip,deflate
+Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
+
+<entry xmlns="http://www.w3.org/2005/Atom"
+ xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
+ xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
+ xml:base="http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/"
+ m:etag="W/2">
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Rooms('2')
+ </id>
+ <title type="text">Room 2</title>
+ <updated>2013-04-03T10:53:26.021+02:00</updated>
+ <category term="RefScenario.Room"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Rooms('2')" rel="edit" title="Room" />
+ <link href="Rooms('2')/nr_Employees"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/nr_Employees"
+ title="nr_Employees" type="application/atom+xml; type=feed">
+ <m:inline>
+ <feed xmlns="http://www.w3.org/2005/Atom"
+ xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
+ xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
+ xml:base="http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/">
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees
+ </id>
+ <title type="text">Employees</title>
+ <updated>2013-04-03T10:53:26.024+02:00</updated>
+ <author>
+ <name />
+ </author>
+ <link href="Employees" rel="self" title="Employees" />
+ <entry>
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees('2')
+ </id>
+ <title type="text">Frederic Fall</title>
+ <updated>2003-07-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('2')" rel="edit" title="Employee" />
+ <link href="Employees('2')/$value" rel="edit-media"
+ type="application/octet-stream" />
+ <link href="Employees('2')/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+ title="ne_Manager" type="application/atom+xml; type=entry" />
+ <link href="Employees('2')/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+ title="ne_Team" type="application/atom+xml; type=entry" />
+ <link href="Employees('2')/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+ title="ne_Room" type="application/atom+xml; type=entry" />
+ <content type="application/octet-stream" src="Employees('2')/$value" />
+ <m:properties>
+ <d:EmployeeId>2</d:EmployeeId>
+ <d:EmployeeName>Frederic Fall</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>2</d:RoomId>
+ <d:TeamId>1</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69190</d:PostalCode>
+ <d:CityName>Walldorf</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>32</d:Age>
+ <d:EntryDate>2003-07-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('2')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees('3')
+ </id>
+ <title type="text">Jonathan Smith</title>
+ <updated>2013-04-03T10:53:26.025+02:00</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('3')" rel="edit" title="Employee" />
+ <link href="Employees('3')/$value" rel="edit-media"
+ type="application/octet-stream" />
+ <link href="Employees('3')/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+ title="ne_Manager" type="application/atom+xml; type=entry" />
+ <link href="Employees('3')/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+ title="ne_Team" type="application/atom+xml; type=entry" />
+ <link href="Employees('3')/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+ title="ne_Room" type="application/atom+xml; type=entry" />
+ <content type="application/octet-stream" src="Employees('3')/$value" />
+ <m:properties>
+ <d:EmployeeId>3</d:EmployeeId>
+ <d:EmployeeName>Jonathan Smith</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>2</d:RoomId>
+ <d:TeamId>1</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69190</d:PostalCode>
+ <d:CityName>Walldorf</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>56</d:Age>
+ <d:EntryDate m:null="true" />
+ <d:ImageUrl>Employees('3')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees('4')
+ </id>
+ <title type="text">Peter Burke</title>
+ <updated>2004-09-12T00:00:00Z</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('4')" rel="edit" title="Employee" />
+ <link href="Employees('4')/$value" rel="edit-media"
+ type="application/octet-stream" />
+ <link href="Employees('4')/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+ title="ne_Manager" type="application/atom+xml; type=entry" />
+ <link href="Employees('4')/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+ title="ne_Team" type="application/atom+xml; type=entry" />
+ <link href="Employees('4')/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+ title="ne_Room" type="application/atom+xml; type=entry" />
+ <content type="application/octet-stream" src="Employees('4')/$value" />
+ <m:properties>
+ <d:EmployeeId>4</d:EmployeeId>
+ <d:EmployeeName>Peter Burke</d:EmployeeName>
+ <d:ManagerId>3</d:ManagerId>
+ <d:RoomId>2</d:RoomId>
+ <d:TeamId>2</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69190</d:PostalCode>
+ <d:CityName>Walldorf</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>39</d:Age>
+ <d:EntryDate>2004-09-12T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('4')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees('6')
+ </id>
+ <title type="text">Susan Bay</title>
+ <updated>2010-12-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('6')" rel="edit" title="Employee" />
+ <link href="Employees('6')/$value" rel="edit-media"
+ type="application/octet-stream" />
+ <link href="Employees('6')/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+ title="ne_Manager" type="application/atom+xml; type=entry" />
+ <link href="Employees('6')/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+ title="ne_Team" type="application/atom+xml; type=entry" />
+ <link href="Employees('6')/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+ title="ne_Room" type="application/atom+xml; type=entry" />
+ <content type="application/octet-stream" src="Employees('6')/$value" />
+ <m:properties>
+ <d:EmployeeId>6</d:EmployeeId>
+ <d:EmployeeName>Susan Bay</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>2</d:RoomId>
+ <d:TeamId>3</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69190</d:PostalCode>
+ <d:CityName>Walldorf</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>29</d:Age>
+ <d:EntryDate>2010-12-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('6')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ </feed>
+ </m:inline>
+ </link>
+ <link href="Rooms('2')/nr_Building"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/nr_Building"
+ title="nr_Building" type="application/atom+xml; type=entry" />
+ <content type="application/xml">
+ <m:properties>
+ <d:Id>2</d:Id>
+ <d:Name>Room 2</d:Name>
+ <d:Seats>5</d:Seats>
+ <d:Version>2</d:Version>
+ </m:properties>
+ </content>
+</entry>
+
+--changeset_f980-1cb6-94dd
+Content-Type: application/http
+Content-Transfer-Encoding: binary
+Content-ID: 1
+
+PUT Employees('1') HTTP/1.1
+Host: http://localhost/odata
+Connection: keep-alive
+Content-Length: 1117
+Authorization: Basic YW56ZWlnZXI6ZGlzcGxheQ==
+Origin: chrome-extension://hgmloofddffdnphfgcellkdfbfbjeloo
+X-CSRF-Token: P6no0PBwygp1ie0Gz-YbEg==
+User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36
+Content-Type: application/atom+xml
+Accept: */*
+Accept-Encoding: gzip,deflate
+Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
+
+<?xml version='1.0' encoding='utf-8'?>
+<entry xmlns="http://www.w3.org/2005/Atom"
+ xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
+ xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
+ xml:base="http://localhost:19000/abc/EntryXmlChangeTest/">
+ <id>http://localhost:19000/abc/EntryXmlChangeTest/Employees('9')</id>
+ <title type="text">Mister X</title>
+ <updated m:null='true'>Z</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <content type="image/jpeg" src="Employees('1')/$value" />
+ <m:properties>
+ <d:EmployeeId>1</d:EmployeeId>
+ <d:EmployeeName>Mister X</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>2</d:RoomId>
+ <d:TeamId>1</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69190</d:PostalCode>
+ <d:CityName>Walldorf</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:EntryDate m:null='true'></d:EntryDate>
+ <d:ImageUrl>Employees('1')/$value</d:ImageUrl>
+ </m:properties>
+</entry>
+--changeset_f980-1cb6-94dd--
+--batch_8194-cf13-1f56
+Content-Type: multipart/mixed; boundary=changeset_f980-1cb6-94dd
+
+--changeset_f980-1cb6-94dd
+Content-Type: application/http
+Content-Transfer-Encoding: binary
+Content-ID: 1
+
+POST Employees HTTP/1.1
+Host: http://localhost/odata
+Connection: keep-alive
+Content-Length: 1117
+Authorization: Basic YW56ZWlnZXI6ZGlzcGxheQ==
+Origin: chrome-extension://hgmloofddffdnphfgcellkdfbfbjeloo
+X-CSRF-Token: P6no0PBwygp1ie0Gz-YbEg==
+User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36
+Content-Type: application/atom+xml
+Accept: */*
+Accept-Encoding: gzip,deflate
+Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
+
+<entry xmlns="http://www.w3.org/2005/Atom"
+ xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
+ xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
+ xml:base="http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/"
+ m:etag="W/2">
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Rooms('2')
+ </id>
+ <title type="text">Room 2</title>
+ <updated>2013-04-03T10:53:26.021+02:00</updated>
+ <category term="RefScenario.Room"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Rooms('2')" rel="edit" title="Room" />
+ <link href="Rooms('2')/nr_Employees"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/nr_Employees"
+ title="nr_Employees" type="application/atom+xml; type=feed">
+ <m:inline>
+ <feed xmlns="http://www.w3.org/2005/Atom"
+ xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
+ xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
+ xml:base="http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/">
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees
+ </id>
+ <title type="text">Employees</title>
+ <updated>2013-04-03T10:53:26.024+02:00</updated>
+ <author>
+ <name />
+ </author>
+ <link href="Employees" rel="self" title="Employees" />
+ <entry>
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees('2')
+ </id>
+ <title type="text">Frederic Fall</title>
+ <updated>2003-07-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('2')" rel="edit" title="Employee" />
+ <link href="Employees('2')/$value" rel="edit-media"
+ type="application/octet-stream" />
+ <link href="Employees('2')/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+ title="ne_Manager" type="application/atom+xml; type=entry" />
+ <link href="Employees('2')/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+ title="ne_Team" type="application/atom+xml; type=entry" />
+ <link href="Employees('2')/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+ title="ne_Room" type="application/atom+xml; type=entry" />
+ <content type="application/octet-stream" src="Employees('2')/$value" />
+ <m:properties>
+ <d:EmployeeId>2</d:EmployeeId>
+ <d:EmployeeName>Frederic Fall</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>2</d:RoomId>
+ <d:TeamId>1</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69190</d:PostalCode>
+ <d:CityName>Walldorf</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>32</d:Age>
+ <d:EntryDate>2003-07-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('2')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees('3')
+ </id>
+ <title type="text">Jonathan Smith</title>
+ <updated>2013-04-03T10:53:26.025+02:00</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('3')" rel="edit" title="Employee" />
+ <link href="Employees('3')/$value" rel="edit-media"
+ type="application/octet-stream" />
+ <link href="Employees('3')/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+ title="ne_Manager" type="application/atom+xml; type=entry" />
+ <link href="Employees('3')/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+ title="ne_Team" type="application/atom+xml; type=entry" />
+ <link href="Employees('3')/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+ title="ne_Room" type="application/atom+xml; type=entry" />
+ <content type="application/octet-stream" src="Employees('3')/$value" />
+ <m:properties>
+ <d:EmployeeId>3</d:EmployeeId>
+ <d:EmployeeName>Jonathan Smith</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>2</d:RoomId>
+ <d:TeamId>1</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69190</d:PostalCode>
+ <d:CityName>Walldorf</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>56</d:Age>
+ <d:EntryDate m:null="true" />
+ <d:ImageUrl>Employees('3')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees('4')
+ </id>
+ <title type="text">Peter Burke</title>
+ <updated>2004-09-12T00:00:00Z</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('4')" rel="edit" title="Employee" />
+ <link href="Employees('4')/$value" rel="edit-media"
+ type="application/octet-stream" />
+ <link href="Employees('4')/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+ title="ne_Manager" type="application/atom+xml; type=entry" />
+ <link href="Employees('4')/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+ title="ne_Team" type="application/atom+xml; type=entry" />
+ <link href="Employees('4')/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+ title="ne_Room" type="application/atom+xml; type=entry" />
+ <content type="application/octet-stream" src="Employees('4')/$value" />
+ <m:properties>
+ <d:EmployeeId>4</d:EmployeeId>
+ <d:EmployeeName>Peter Burke</d:EmployeeName>
+ <d:ManagerId>3</d:ManagerId>
+ <d:RoomId>2</d:RoomId>
+ <d:TeamId>2</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69190</d:PostalCode>
+ <d:CityName>Walldorf</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>39</d:Age>
+ <d:EntryDate>2004-09-12T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('4')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees('6')
+ </id>
+ <title type="text">Susan Bay</title>
+ <updated>2010-12-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('6')" rel="edit" title="Employee" />
+ <link href="Employees('6')/$value" rel="edit-media"
+ type="application/octet-stream" />
+ <link href="Employees('6')/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+ title="ne_Manager" type="application/atom+xml; type=entry" />
+ <link href="Employees('6')/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+ title="ne_Team" type="application/atom+xml; type=entry" />
+ <link href="Employees('6')/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+ title="ne_Room" type="application/atom+xml; type=entry" />
+ <content type="application/octet-stream" src="Employees('6')/$value" />
+ <m:properties>
+ <d:EmployeeId>6</d:EmployeeId>
+ <d:EmployeeName>Susan Bay</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>2</d:RoomId>
+ <d:TeamId>3</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69190</d:PostalCode>
+ <d:CityName>Walldorf</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>29</d:Age>
+ <d:EntryDate>2010-12-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('6')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ </feed>
+ </m:inline>
+ </link>
+ <link href="Rooms('2')/nr_Building"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/nr_Building"
+ title="nr_Building" type="application/atom+xml; type=entry" />
+ <content type="application/xml">
+ <m:properties>
+ <d:Id>2</d:Id>
+ <d:Name>Room 2</d:Name>
+ <d:Seats>5</d:Seats>
+ <d:Version>2</d:Version>
+ </m:properties>
+ </content>
+</entry>
+
+--changeset_f980-1cb6-94dd
+Content-Type: application/http
+Content-Transfer-Encoding: binary
+Content-ID: 1
+
+POST Employees HTTP/1.1
+Host: http://localhost/odata
+Connection: keep-alive
+Content-Length: 1117
+Authorization: Basic YW56ZWlnZXI6ZGlzcGxheQ==
+Origin: chrome-extension://hgmloofddffdnphfgcellkdfbfbjeloo
+X-CSRF-Token: P6no0PBwygp1ie0Gz-YbEg==
+User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36
+Content-Type: application/atom+xml
+Accept: */*
+Accept-Encoding: gzip,deflate
+Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
+
+<entry xmlns="http://www.w3.org/2005/Atom"
+ xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
+ xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
+ xml:base="http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/"
+ m:etag="W/2">
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Rooms('2')
+ </id>
+ <title type="text">Room 2</title>
+ <updated>2013-04-03T10:53:26.021+02:00</updated>
+ <category term="RefScenario.Room"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Rooms('2')" rel="edit" title="Room" />
+ <link href="Rooms('2')/nr_Employees"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/nr_Employees"
+ title="nr_Employees" type="application/atom+xml; type=feed">
+ <m:inline>
+ <feed xmlns="http://www.w3.org/2005/Atom"
+ xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
+ xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
+ xml:base="http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/">
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees
+ </id>
+ <title type="text">Employees</title>
+ <updated>2013-04-03T10:53:26.024+02:00</updated>
+ <author>
+ <name />
+ </author>
+ <link href="Employees" rel="self" title="Employees" />
+ <entry>
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees('2')
+ </id>
+ <title type="text">Frederic Fall</title>
+ <updated>2003-07-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('2')" rel="edit" title="Employee" />
+ <link href="Employees('2')/$value" rel="edit-media"
+ type="application/octet-stream" />
+ <link href="Employees('2')/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+ title="ne_Manager" type="application/atom+xml; type=entry" />
+ <link href="Employees('2')/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+ title="ne_Team" type="application/atom+xml; type=entry" />
+ <link href="Employees('2')/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+ title="ne_Room" type="application/atom+xml; type=entry" />
+ <content type="application/octet-stream" src="Employees('2')/$value" />
+ <m:properties>
+ <d:EmployeeId>2</d:EmployeeId>
+ <d:EmployeeName>Frederic Fall</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>2</d:RoomId>
+ <d:TeamId>1</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69190</d:PostalCode>
+ <d:CityName>Walldorf</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>32</d:Age>
+ <d:EntryDate>2003-07-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('2')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees('3')
+ </id>
+ <title type="text">Jonathan Smith</title>
+ <updated>2013-04-03T10:53:26.025+02:00</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('3')" rel="edit" title="Employee" />
+ <link href="Employees('3')/$value" rel="edit-media"
+ type="application/octet-stream" />
+ <link href="Employees('3')/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+ title="ne_Manager" type="application/atom+xml; type=entry" />
+ <link href="Employees('3')/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+ title="ne_Team" type="application/atom+xml; type=entry" />
+ <link href="Employees('3')/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+ title="ne_Room" type="application/atom+xml; type=entry" />
+ <content type="application/octet-stream" src="Employees('3')/$value" />
+ <m:properties>
+ <d:EmployeeId>3</d:EmployeeId>
+ <d:EmployeeName>Jonathan Smith</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>2</d:RoomId>
+ <d:TeamId>1</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69190</d:PostalCode>
+ <d:CityName>Walldorf</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>56</d:Age>
+ <d:EntryDate m:null="true" />
+ <d:ImageUrl>Employees('3')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees('4')
+ </id>
+ <title type="text">Peter Burke</title>
+ <updated>2004-09-12T00:00:00Z</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('4')" rel="edit" title="Employee" />
+ <link href="Employees('4')/$value" rel="edit-media"
+ type="application/octet-stream" />
+ <link href="Employees('4')/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+ title="ne_Manager" type="application/atom+xml; type=entry" />
+ <link href="Employees('4')/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+ title="ne_Team" type="application/atom+xml; type=entry" />
+ <link href="Employees('4')/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+ title="ne_Room" type="application/atom+xml; type=entry" />
+ <content type="application/octet-stream" src="Employees('4')/$value" />
+ <m:properties>
+ <d:EmployeeId>4</d:EmployeeId>
+ <d:EmployeeName>Peter Burke</d:EmployeeName>
+ <d:ManagerId>3</d:ManagerId>
+ <d:RoomId>2</d:RoomId>
+ <d:TeamId>2</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69190</d:PostalCode>
+ <d:CityName>Walldorf</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>39</d:Age>
+ <d:EntryDate>2004-09-12T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('4')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees('6')
+ </id>
+ <title type="text">Susan Bay</title>
+ <updated>2010-12-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('6')" rel="edit" title="Employee" />
+ <link href="Employees('6')/$value" rel="edit-media"
+ type="application/octet-stream" />
+ <link href="Employees('6')/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+ title="ne_Manager" type="application/atom+xml; type=entry" />
+ <link href="Employees('6')/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+ title="ne_Team" type="application/atom+xml; type=entry" />
+ <link href="Employees('6')/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+ title="ne_Room" type="application/atom+xml; type=entry" />
+ <content type="application/octet-stream" src="Employees('6')/$value" />
+ <m:properties>
+ <d:EmployeeId>6</d:EmployeeId>
+ <d:EmployeeName>Susan Bay</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>2</d:RoomId>
+ <d:TeamId>3</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69190</d:PostalCode>
+ <d:CityName>Walldorf</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>29</d:Age>
+ <d:EntryDate>2010-12-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('6')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ </feed>
+ </m:inline>
+ </link>
+ <link href="Rooms('2')/nr_Building"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/nr_Building"
+ title="nr_Building" type="application/atom+xml; type=entry" />
+ <content type="application/xml">
+ <m:properties>
+ <d:Id>2</d:Id>
+ <d:Name>Room 2</d:Name>
+ <d:Seats>5</d:Seats>
+ <d:Version>2</d:Version>
+ </m:properties>
+ </content>
+</entry>
+
+--changeset_f980-1cb6-94dd
+Content-Type: application/http
+Content-Transfer-Encoding: binary
+Content-ID: 1
+
+PUT Employees('1') HTTP/1.1
+Host: http://localhost/odata
+Connection: keep-alive
+Content-Length: 1117
+Authorization: Basic YW56ZWlnZXI6ZGlzcGxheQ==
+Origin: chrome-extension://hgmloofddffdnphfgcellkdfbfbjeloo
+X-CSRF-Token: P6no0PBwygp1ie0Gz-YbEg==
+User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36
+Content-Type: application/atom+xml
+Accept: */*
+Accept-Encoding: gzip,deflate
+Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
+
+<?xml version='1.0' encoding='utf-8'?>
+<entry xmlns="http://www.w3.org/2005/Atom"
+ xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
+ xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
+ xml:base="http://localhost:19000/abc/EntryXmlChangeTest/">
+ <id>http://localhost:19000/abc/EntryXmlChangeTest/Employees('9')</id>
+ <title type="text">Mister X</title>
+ <updated m:null='true'>Z</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <content type="image/jpeg" src="Employees('1')/$value" />
+ <m:properties>
+ <d:EmployeeId>1</d:EmployeeId>
+ <d:EmployeeName>Mister X</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>2</d:RoomId>
+ <d:TeamId>1</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69190</d:PostalCode>
+ <d:CityName>Walldorf</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:EntryDate m:null='true'></d:EntryDate>
+ <d:ImageUrl>Employees('1')/$value</d:ImageUrl>
+ </m:properties>
+</entry>
+--changeset_f980-1cb6-94dd--
+--batch_8194-cf13-1f56
+Content-Type: multipart/mixed; boundary=changeset_f980-1cb6-94dd
+
+--changeset_f980-1cb6-94dd
+Content-Type: application/http
+Content-Transfer-Encoding: binary
+Content-ID: 1
+
+POST Employees HTTP/1.1
+Host: http://localhost/odata
+Connection: keep-alive
+Content-Length: 1117
+Authorization: Basic YW56ZWlnZXI6ZGlzcGxheQ==
+Origin: chrome-extension://hgmloofddffdnphfgcellkdfbfbjeloo
+X-CSRF-Token: P6no0PBwygp1ie0Gz-YbEg==
+User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36
+Content-Type: application/atom+xml
+Accept: */*
+Accept-Encoding: gzip,deflate
+Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
+
+<entry xmlns="http://www.w3.org/2005/Atom"
+ xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
+ xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
+ xml:base="http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/"
+ m:etag="W/2">
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Rooms('2')
+ </id>
+ <title type="text">Room 2</title>
+ <updated>2013-04-03T10:53:26.021+02:00</updated>
+ <category term="RefScenario.Room"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Rooms('2')" rel="edit" title="Room" />
+ <link href="Rooms('2')/nr_Employees"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/nr_Employees"
+ title="nr_Employees" type="application/atom+xml; type=feed">
+ <m:inline>
+ <feed xmlns="http://www.w3.org/2005/Atom"
+ xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
+ xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
+ xml:base="http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/">
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees
+ </id>
+ <title type="text">Employees</title>
+ <updated>2013-04-03T10:53:26.024+02:00</updated>
+ <author>
+ <name />
+ </author>
+ <link href="Employees" rel="self" title="Employees" />
+ <entry>
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees('2')
+ </id>
+ <title type="text">Frederic Fall</title>
+ <updated>2003-07-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('2')" rel="edit" title="Employee" />
+ <link href="Employees('2')/$value" rel="edit-media"
+ type="application/octet-stream" />
+ <link href="Employees('2')/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+ title="ne_Manager" type="application/atom+xml; type=entry" />
+ <link href="Employees('2')/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+ title="ne_Team" type="application/atom+xml; type=entry" />
+ <link href="Employees('2')/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+ title="ne_Room" type="application/atom+xml; type=entry" />
+ <content type="application/octet-stream" src="Employees('2')/$value" />
+ <m:properties>
+ <d:EmployeeId>2</d:EmployeeId>
+ <d:EmployeeName>Frederic Fall</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>2</d:RoomId>
+ <d:TeamId>1</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69190</d:PostalCode>
+ <d:CityName>Walldorf</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>32</d:Age>
+ <d:EntryDate>2003-07-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('2')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees('3')
+ </id>
+ <title type="text">Jonathan Smith</title>
+ <updated>2013-04-03T10:53:26.025+02:00</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('3')" rel="edit" title="Employee" />
+ <link href="Employees('3')/$value" rel="edit-media"
+ type="application/octet-stream" />
+ <link href="Employees('3')/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+ title="ne_Manager" type="application/atom+xml; type=entry" />
+ <link href="Employees('3')/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+ title="ne_Team" type="application/atom+xml; type=entry" />
+ <link href="Employees('3')/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+ title="ne_Room" type="application/atom+xml; type=entry" />
+ <content type="application/octet-stream" src="Employees('3')/$value" />
+ <m:properties>
+ <d:EmployeeId>3</d:EmployeeId>
+ <d:EmployeeName>Jonathan Smith</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>2</d:RoomId>
+ <d:TeamId>1</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69190</d:PostalCode>
+ <d:CityName>Walldorf</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>56</d:Age>
+ <d:EntryDate m:null="true" />
+ <d:ImageUrl>Employees('3')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees('4')
+ </id>
+ <title type="text">Peter Burke</title>
+ <updated>2004-09-12T00:00:00Z</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('4')" rel="edit" title="Employee" />
+ <link href="Employees('4')/$value" rel="edit-media"
+ type="application/octet-stream" />
+ <link href="Employees('4')/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+ title="ne_Manager" type="application/atom+xml; type=entry" />
+ <link href="Employees('4')/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+ title="ne_Team" type="application/atom+xml; type=entry" />
+ <link href="Employees('4')/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+ title="ne_Room" type="application/atom+xml; type=entry" />
+ <content type="application/octet-stream" src="Employees('4')/$value" />
+ <m:properties>
+ <d:EmployeeId>4</d:EmployeeId>
+ <d:EmployeeName>Peter Burke</d:EmployeeName>
+ <d:ManagerId>3</d:ManagerId>
+ <d:RoomId>2</d:RoomId>
+ <d:TeamId>2</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69190</d:PostalCode>
+ <d:CityName>Walldorf</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>39</d:Age>
+ <d:EntryDate>2004-09-12T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('4')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees('6')
+ </id>
+ <title type="text">Susan Bay</title>
+ <updated>2010-12-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('6')" rel="edit" title="Employee" />
+ <link href="Employees('6')/$value" rel="edit-media"
+ type="application/octet-stream" />
+ <link href="Employees('6')/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+ title="ne_Manager" type="application/atom+xml; type=entry" />
+ <link href="Employees('6')/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+ title="ne_Team" type="application/atom+xml; type=entry" />
+ <link href="Employees('6')/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+ title="ne_Room" type="application/atom+xml; type=entry" />
+ <content type="application/octet-stream" src="Employees('6')/$value" />
+ <m:properties>
+ <d:EmployeeId>6</d:EmployeeId>
+ <d:EmployeeName>Susan Bay</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>2</d:RoomId>
+ <d:TeamId>3</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69190</d:PostalCode>
+ <d:CityName>Walldorf</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>29</d:Age>
+ <d:EntryDate>2010-12-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('6')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ </feed>
+ </m:inline>
+ </link>
+ <link href="Rooms('2')/nr_Building"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/nr_Building"
+ title="nr_Building" type="application/atom+xml; type=entry" />
+ <content type="application/xml">
+ <m:properties>
+ <d:Id>2</d:Id>
+ <d:Name>Room 2</d:Name>
+ <d:Seats>5</d:Seats>
+ <d:Version>2</d:Version>
+ </m:properties>
+ </content>
+</entry>
+
+--changeset_f980-1cb6-94dd
+Content-Type: application/http
+Content-Transfer-Encoding: binary
+Content-ID: 1
+
+POST Employees HTTP/1.1
+Host: http://localhost/odata
+Connection: keep-alive
+Content-Length: 1117
+Authorization: Basic YW56ZWlnZXI6ZGlzcGxheQ==
+Origin: chrome-extension://hgmloofddffdnphfgcellkdfbfbjeloo
+X-CSRF-Token: P6no0PBwygp1ie0Gz-YbEg==
+User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36
+Content-Type: application/atom+xml
+Accept: */*
+Accept-Encoding: gzip,deflate
+Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
+
+<entry xmlns="http://www.w3.org/2005/Atom"
+ xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
+ xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
+ xml:base="http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/"
+ m:etag="W/2">
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Rooms('2')
+ </id>
+ <title type="text">Room 2</title>
+ <updated>2013-04-03T10:53:26.021+02:00</updated>
+ <category term="RefScenario.Room"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Rooms('2')" rel="edit" title="Room" />
+ <link href="Rooms('2')/nr_Employees"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/nr_Employees"
+ title="nr_Employees" type="application/atom+xml; type=feed">
+ <m:inline>
+ <feed xmlns="http://www.w3.org/2005/Atom"
+ xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
+ xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
+ xml:base="http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/">
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees
+ </id>
+ <title type="text">Employees</title>
+ <updated>2013-04-03T10:53:26.024+02:00</updated>
+ <author>
+ <name />
+ </author>
+ <link href="Employees" rel="self" title="Employees" />
+ <entry>
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees('2')
+ </id>
+ <title type="text">Frederic Fall</title>
+ <updated>2003-07-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('2')" rel="edit" title="Employee" />
+ <link href="Employees('2')/$value" rel="edit-media"
+ type="application/octet-stream" />
+ <link href="Employees('2')/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+ title="ne_Manager" type="application/atom+xml; type=entry" />
+ <link href="Employees('2')/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+ title="ne_Team" type="application/atom+xml; type=entry" />
+ <link href="Employees('2')/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+ title="ne_Room" type="application/atom+xml; type=entry" />
+ <content type="application/octet-stream" src="Employees('2')/$value" />
+ <m:properties>
+ <d:EmployeeId>2</d:EmployeeId>
+ <d:EmployeeName>Frederic Fall</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>2</d:RoomId>
+ <d:TeamId>1</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69190</d:PostalCode>
+ <d:CityName>Walldorf</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>32</d:Age>
+ <d:EntryDate>2003-07-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('2')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees('3')
+ </id>
+ <title type="text">Jonathan Smith</title>
+ <updated>2013-04-03T10:53:26.025+02:00</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('3')" rel="edit" title="Employee" />
+ <link href="Employees('3')/$value" rel="edit-media"
+ type="application/octet-stream" />
+ <link href="Employees('3')/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+ title="ne_Manager" type="application/atom+xml; type=entry" />
+ <link href="Employees('3')/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+ title="ne_Team" type="application/atom+xml; type=entry" />
+ <link href="Employees('3')/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+ title="ne_Room" type="application/atom+xml; type=entry" />
+ <content type="application/octet-stream" src="Employees('3')/$value" />
+ <m:properties>
+ <d:EmployeeId>3</d:EmployeeId>
+ <d:EmployeeName>Jonathan Smith</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>2</d:RoomId>
+ <d:TeamId>1</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69190</d:PostalCode>
+ <d:CityName>Walldorf</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>56</d:Age>
+ <d:EntryDate m:null="true" />
+ <d:ImageUrl>Employees('3')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees('4')
+ </id>
+ <title type="text">Peter Burke</title>
+ <updated>2004-09-12T00:00:00Z</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('4')" rel="edit" title="Employee" />
+ <link href="Employees('4')/$value" rel="edit-media"
+ type="application/octet-stream" />
+ <link href="Employees('4')/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+ title="ne_Manager" type="application/atom+xml; type=entry" />
+ <link href="Employees('4')/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+ title="ne_Team" type="application/atom+xml; type=entry" />
+ <link href="Employees('4')/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+ title="ne_Room" type="application/atom+xml; type=entry" />
+ <content type="application/octet-stream" src="Employees('4')/$value" />
+ <m:properties>
+ <d:EmployeeId>4</d:EmployeeId>
+ <d:EmployeeName>Peter Burke</d:EmployeeName>
+ <d:ManagerId>3</d:ManagerId>
+ <d:RoomId>2</d:RoomId>
+ <d:TeamId>2</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69190</d:PostalCode>
+ <d:CityName>Walldorf</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>39</d:Age>
+ <d:EntryDate>2004-09-12T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('4')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees('6')
+ </id>
+ <title type="text">Susan Bay</title>
+ <updated>2010-12-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('6')" rel="edit" title="Employee" />
+ <link href="Employees('6')/$value" rel="edit-media"
+ type="application/octet-stream" />
+ <link href="Employees('6')/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+ title="ne_Manager" type="application/atom+xml; type=entry" />
+ <link href="Employees('6')/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+ title="ne_Team" type="application/atom+xml; type=entry" />
+ <link href="Employees('6')/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+ title="ne_Room" type="application/atom+xml; type=entry" />
+ <content type="application/octet-stream" src="Employees('6')/$value" />
+ <m:properties>
+ <d:EmployeeId>6</d:EmployeeId>
+ <d:EmployeeName>Susan Bay</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>2</d:RoomId>
+ <d:TeamId>3</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69190</d:PostalCode>
+ <d:CityName>Walldorf</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>29</d:Age>
+ <d:EntryDate>2010-12-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('6')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ </feed>
+ </m:inline>
+ </link>
+ <link href="Rooms('2')/nr_Building"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/nr_Building"
+ title="nr_Building" type="application/atom+xml; type=entry" />
+ <content type="application/xml">
+ <m:properties>
+ <d:Id>2</d:Id>
+ <d:Name>Room 2</d:Name>
+ <d:Seats>5</d:Seats>
+ <d:Version>2</d:Version>
+ </m:properties>
+ </content>
+</entry>
+
+--changeset_f980-1cb6-94dd
+Content-Type: application/http
+Content-Transfer-Encoding: binary
+Content-ID: 1
+
+PUT Employees('1') HTTP/1.1
+Host: http://localhost/odata
+Connection: keep-alive
+Content-Length: 1117
+Authorization: Basic YW56ZWlnZXI6ZGlzcGxheQ==
+Origin: chrome-extension://hgmloofddffdnphfgcellkdfbfbjeloo
+X-CSRF-Token: P6no0PBwygp1ie0Gz-YbEg==
+User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36
+Content-Type: application/atom+xml
+Accept: */*
+Accept-Encoding: gzip,deflate
+Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
+
+<?xml version='1.0' encoding='utf-8'?>
+<entry xmlns="http://www.w3.org/2005/Atom"
+ xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
+ xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
+ xml:base="http://localhost:19000/abc/EntryXmlChangeTest/">
+ <id>http://localhost:19000/abc/EntryXmlChangeTest/Employees('9')</id>
+ <title type="text">Mister X</title>
+ <updated m:null='true'>Z</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <content type="image/jpeg" src="Employees('1')/$value" />
+ <m:properties>
+ <d:EmployeeId>1</d:EmployeeId>
+ <d:EmployeeName>Mister X</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>2</d:RoomId>
+ <d:TeamId>1</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69190</d:PostalCode>
+ <d:CityName>Walldorf</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:EntryDate m:null='true'></d:EntryDate>
+ <d:ImageUrl>Employees('1')/$value</d:ImageUrl>
+ </m:properties>
+</entry>
+--changeset_f980-1cb6-94dd--
+--batch_8194-cf13-1f56
+Content-Type: multipart/mixed; boundary=changeset_f980-1cb6-94dd
+
+--changeset_f980-1cb6-94dd
+Content-Type: application/http
+Content-Transfer-Encoding: binary
+Content-ID: 1
+
+POST Employees HTTP/1.1
+Host: http://localhost/odata
+Connection: keep-alive
+Content-Length: 1117
+Authorization: Basic YW56ZWlnZXI6ZGlzcGxheQ==
+Origin: chrome-extension://hgmloofddffdnphfgcellkdfbfbjeloo
+X-CSRF-Token: P6no0PBwygp1ie0Gz-YbEg==
+User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36
+Content-Type: application/atom+xml
+Accept: */*
+Accept-Encoding: gzip,deflate
+Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
+
+<entry xmlns="http://www.w3.org/2005/Atom"
+ xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
+ xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
+ xml:base="http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/"
+ m:etag="W/2">
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Rooms('2')
+ </id>
+ <title type="text">Room 2</title>
+ <updated>2013-04-03T10:53:26.021+02:00</updated>
+ <category term="RefScenario.Room"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Rooms('2')" rel="edit" title="Room" />
+ <link href="Rooms('2')/nr_Employees"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/nr_Employees"
+ title="nr_Employees" type="application/atom+xml; type=feed">
+ <m:inline>
+ <feed xmlns="http://www.w3.org/2005/Atom"
+ xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
+ xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
+ xml:base="http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/">
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees
+ </id>
+ <title type="text">Employees</title>
+ <updated>2013-04-03T10:53:26.024+02:00</updated>
+ <author>
+ <name />
+ </author>
+ <link href="Employees" rel="self" title="Employees" />
+ <entry>
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees('2')
+ </id>
+ <title type="text">Frederic Fall</title>
+ <updated>2003-07-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('2')" rel="edit" title="Employee" />
+ <link href="Employees('2')/$value" rel="edit-media"
+ type="application/octet-stream" />
+ <link href="Employees('2')/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+ title="ne_Manager" type="application/atom+xml; type=entry" />
+ <link href="Employees('2')/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+ title="ne_Team" type="application/atom+xml; type=entry" />
+ <link href="Employees('2')/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+ title="ne_Room" type="application/atom+xml; type=entry" />
+ <content type="application/octet-stream" src="Employees('2')/$value" />
+ <m:properties>
+ <d:EmployeeId>2</d:EmployeeId>
+ <d:EmployeeName>Frederic Fall</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>2</d:RoomId>
+ <d:TeamId>1</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69190</d:PostalCode>
+ <d:CityName>Walldorf</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>32</d:Age>
+ <d:EntryDate>2003-07-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('2')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees('3')
+ </id>
+ <title type="text">Jonathan Smith</title>
+ <updated>2013-04-03T10:53:26.025+02:00</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('3')" rel="edit" title="Employee" />
+ <link href="Employees('3')/$value" rel="edit-media"
+ type="application/octet-stream" />
+ <link href="Employees('3')/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+ title="ne_Manager" type="application/atom+xml; type=entry" />
+ <link href="Employees('3')/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+ title="ne_Team" type="application/atom+xml; type=entry" />
+ <link href="Employees('3')/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+ title="ne_Room" type="application/atom+xml; type=entry" />
+ <content type="application/octet-stream" src="Employees('3')/$value" />
+ <m:properties>
+ <d:EmployeeId>3</d:EmployeeId>
+ <d:EmployeeName>Jonathan Smith</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>2</d:RoomId>
+ <d:TeamId>1</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69190</d:PostalCode>
+ <d:CityName>Walldorf</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>56</d:Age>
+ <d:EntryDate m:null="true" />
+ <d:ImageUrl>Employees('3')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees('4')
+ </id>
+ <title type="text">Peter Burke</title>
+ <updated>2004-09-12T00:00:00Z</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('4')" rel="edit" title="Employee" />
+ <link href="Employees('4')/$value" rel="edit-media"
+ type="application/octet-stream" />
+ <link href="Employees('4')/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+ title="ne_Manager" type="application/atom+xml; type=entry" />
+ <link href="Employees('4')/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+ title="ne_Team" type="application/atom+xml; type=entry" />
+ <link href="Employees('4')/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+ title="ne_Room" type="application/atom+xml; type=entry" />
+ <content type="application/octet-stream" src="Employees('4')/$value" />
+ <m:properties>
+ <d:EmployeeId>4</d:EmployeeId>
+ <d:EmployeeName>Peter Burke</d:EmployeeName>
+ <d:ManagerId>3</d:ManagerId>
+ <d:RoomId>2</d:RoomId>
+ <d:TeamId>2</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69190</d:PostalCode>
+ <d:CityName>Walldorf</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>39</d:Age>
+ <d:EntryDate>2004-09-12T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('4')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees('6')
+ </id>
+ <title type="text">Susan Bay</title>
+ <updated>2010-12-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('6')" rel="edit" title="Employee" />
+ <link href="Employees('6')/$value" rel="edit-media"
+ type="application/octet-stream" />
+ <link href="Employees('6')/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+ title="ne_Manager" type="application/atom+xml; type=entry" />
+ <link href="Employees('6')/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+ title="ne_Team" type="application/atom+xml; type=entry" />
+ <link href="Employees('6')/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+ title="ne_Room" type="application/atom+xml; type=entry" />
+ <content type="application/octet-stream" src="Employees('6')/$value" />
+ <m:properties>
+ <d:EmployeeId>6</d:EmployeeId>
+ <d:EmployeeName>Susan Bay</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>2</d:RoomId>
+ <d:TeamId>3</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69190</d:PostalCode>
+ <d:CityName>Walldorf</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>29</d:Age>
+ <d:EntryDate>2010-12-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('6')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ </feed>
+ </m:inline>
+ </link>
+ <link href="Rooms('2')/nr_Building"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/nr_Building"
+ title="nr_Building" type="application/atom+xml; type=entry" />
+ <content type="application/xml">
+ <m:properties>
+ <d:Id>2</d:Id>
+ <d:Name>Room 2</d:Name>
+ <d:Seats>5</d:Seats>
+ <d:Version>2</d:Version>
+ </m:properties>
+ </content>
+</entry>
+
+--changeset_f980-1cb6-94dd
+Content-Type: application/http
+Content-Transfer-Encoding: binary
+Content-ID: 1
+
+POST Employees HTTP/1.1
+Host: http://localhost/odata
+Connection: keep-alive
+Content-Length: 1117
+Authorization: Basic YW56ZWlnZXI6ZGlzcGxheQ==
+Origin: chrome-extension://hgmloofddffdnphfgcellkdfbfbjeloo
+X-CSRF-Token: P6no0PBwygp1ie0Gz-YbEg==
+User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36
+Content-Type: application/atom+xml
+Accept: */*
+Accept-Encoding: gzip,deflate
+Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
+
+<entry xmlns="http://www.w3.org/2005/Atom"
+ xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
+ xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
+ xml:base="http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/"
+ m:etag="W/2">
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Rooms('2')
+ </id>
+ <title type="text">Room 2</title>
+ <updated>2013-04-03T10:53:26.021+02:00</updated>
+ <category term="RefScenario.Room"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Rooms('2')" rel="edit" title="Room" />
+ <link href="Rooms('2')/nr_Employees"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/nr_Employees"
+ title="nr_Employees" type="application/atom+xml; type=feed">
+ <m:inline>
+ <feed xmlns="http://www.w3.org/2005/Atom"
+ xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
+ xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
+ xml:base="http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/">
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees
+ </id>
+ <title type="text">Employees</title>
+ <updated>2013-04-03T10:53:26.024+02:00</updated>
+ <author>
+ <name />
+ </author>
+ <link href="Employees" rel="self" title="Employees" />
+ <entry>
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees('2')
+ </id>
+ <title type="text">Frederic Fall</title>
+ <updated>2003-07-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('2')" rel="edit" title="Employee" />
+ <link href="Employees('2')/$value" rel="edit-media"
+ type="application/octet-stream" />
+ <link href="Employees('2')/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+ title="ne_Manager" type="application/atom+xml; type=entry" />
+ <link href="Employees('2')/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+ title="ne_Team" type="application/atom+xml; type=entry" />
+ <link href="Employees('2')/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+ title="ne_Room" type="application/atom+xml; type=entry" />
+ <content type="application/octet-stream" src="Employees('2')/$value" />
+ <m:properties>
+ <d:EmployeeId>2</d:EmployeeId>
+ <d:EmployeeName>Frederic Fall</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>2</d:RoomId>
+ <d:TeamId>1</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69190</d:PostalCode>
+ <d:CityName>Walldorf</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>32</d:Age>
+ <d:EntryDate>2003-07-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('2')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>
+ http://localhost:8080/org.apache.olingo.odata2.ref.web/ReferenceScenario.svc/Employees('3')
+ </id>
+ <title type="text">Jonathan Smith</title>
+ <updated>2013-04-03T10:53:26.025+02:00</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('3')" rel="edit" title="Employee" />
+ <link href="Employees('3')/$value" rel="edit-media"
+ type="application/octet-stream" />
+ <link href="Employees('3')/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+ title="ne_Manager" type="application/atom+xml; type=entry" />
+ <link href="Employees('3')/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+ title="ne_Team" type="application/atom+xml; type=entry" />
+ <link href="Employees('3')/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+ title="ne_Room" type="application/atom+xml; type=entry" />
+ <content type="application/octet-stream" src="Employees('3')/$value" />
+ <m:properties>
+ <d:EmployeeId>3</d:EmployeeId>
+ <d:EmployeeName>Jonathan Smith</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>2</d:RoomId>
+ <d:TeamId>1</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69190</d:PostalCode>
+ <d:CityName>Walldorf</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>56</d:Age>
+ <d:EntryDate m:null="true" />
+ <d:Im
<TRUNCATED>