You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by mi...@apache.org on 2014/05/09 14:47:14 UTC
[1/6] [OLINGO-231] Several refactorings
Repository: olingo-odata2
Updated Branches:
refs/heads/OLINGO-231_PocForAndroid 696288d17 -> cb1ba4685
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb1ba468/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/BaseNCodec.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/BaseNCodec.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/BaseNCodec.java
new file mode 100644
index 0000000..f8097c5
--- /dev/null
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/BaseNCodec.java
@@ -0,0 +1,350 @@
+/*
+ * 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.commons;
+
+import java.io.UnsupportedEncodingException;
+
+/**
+ * Abstract superclass for Base-N encoders and decoders.
+ *
+ * <p>
+ * This class is not thread-safe.
+ * Each thread should use its own instance.
+ * </p>
+ */
+public abstract class BaseNCodec {
+
+ /**
+ * MIME chunk size per RFC 2045 section 6.8.
+ *
+ * <p>
+ * The {@value} character limit does not count the trailing CRLF, but counts all other characters, including any
+ * equal signs.
+ * </p>
+ *
+ * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045 section 6.8</a>
+ */
+ public static final int MIME_CHUNK_SIZE = 76;
+
+ private static final int DEFAULT_BUFFER_RESIZE_FACTOR = 2;
+
+ /**
+ * Defines the default buffer size - currently {@value}
+ * - must be large enough for at least one encoded block+separator
+ */
+ private static final int DEFAULT_BUFFER_SIZE = 8192;
+
+ /** Mask used to extract 8 bits, used in decoding bytes */
+ protected static final int MASK_8BITS = 0xff;
+
+ /**
+ * Byte used to pad output.
+ */
+ protected static final byte PAD_DEFAULT = '='; // Allow static access to default
+
+ protected final byte PAD = PAD_DEFAULT; // instance variable just in case it needs to vary later
+
+ /** Number of bytes in each full block of unencoded data, e.g. 4 for Base64 and 5 for Base32 */
+ private final int unencodedBlockSize;
+
+ /** Number of bytes in each full block of encoded data, e.g. 3 for Base64 and 8 for Base32 */
+ private final int encodedBlockSize;
+
+ /**
+ * Chunksize for encoding. Not used when decoding.
+ * A value of zero or less implies no chunking of the encoded data.
+ * Rounded down to nearest multiple of encodedBlockSize.
+ */
+ protected final int lineLength;
+
+ /**
+ * Size of chunk separator. Not used unless {@link #lineLength} > 0.
+ */
+ private final int chunkSeparatorLength;
+
+ /**
+ * Buffer for streaming.
+ */
+ protected byte[] buffer;
+
+ /**
+ * Position where next character should be written in the buffer.
+ */
+ protected int pos;
+
+ /**
+ * Position where next character should be read from the buffer.
+ */
+ private int readPos;
+
+ /**
+ * Boolean flag to indicate the EOF has been reached. Once EOF has been reached, this object becomes useless,
+ * and must be thrown away.
+ */
+ protected boolean eof;
+
+ /**
+ * Variable tracks how many characters have been written to the current line. Only used when encoding. We use it to
+ * make sure each encoded line never goes beyond lineLength (if lineLength > 0).
+ */
+ protected int currentLinePos;
+
+ /**
+ * Writes to the buffer only occur after every 3/5 reads when encoding, and every 4/8 reads when decoding.
+ * This variable helps track that.
+ */
+ protected int modulus;
+
+ /**
+ * Note <code>lineLength</code> is rounded down to the nearest multiple of {@link #encodedBlockSize}
+ * If <code>chunkSeparatorLength</code> is zero, then chunking is disabled.
+ * @param unencodedBlockSize the size of an unencoded block (e.g. Base64 = 3)
+ * @param encodedBlockSize the size of an encoded block (e.g. Base64 = 4)
+ * @param lineLength if > 0, use chunking with a length <code>lineLength</code>
+ * @param chunkSeparatorLength the chunk separator length, if relevant
+ */
+ protected BaseNCodec(int unencodedBlockSize, int encodedBlockSize, int lineLength, int chunkSeparatorLength){
+ this.unencodedBlockSize = unencodedBlockSize;
+ this.encodedBlockSize = encodedBlockSize;
+ this.lineLength = (lineLength > 0 && chunkSeparatorLength > 0) ?
+ (lineLength / encodedBlockSize) * encodedBlockSize
+ : 0;
+ this.chunkSeparatorLength = chunkSeparatorLength;
+ }
+
+ /**
+ * Returns the amount of buffered data available for reading.
+ *
+ * @return The amount of buffered data available for reading.
+ */
+ int available() { // package protected for access from I/O streams
+ return buffer != null ? pos - readPos : 0;
+ }
+
+ /**
+ * Get the default buffer size. Can be overridden.
+ *
+ * @return {@link #DEFAULT_BUFFER_SIZE}
+ */
+ protected int getDefaultBufferSize() {
+ return DEFAULT_BUFFER_SIZE;
+ }
+
+ /** Increases our buffer by the {@link #DEFAULT_BUFFER_RESIZE_FACTOR}. */
+ private void resizeBuffer() {
+ if (buffer == null) {
+ buffer = new byte[getDefaultBufferSize()];
+ pos = 0;
+ readPos = 0;
+ } else {
+ byte[] b = new byte[buffer.length * DEFAULT_BUFFER_RESIZE_FACTOR];
+ System.arraycopy(buffer, 0, b, 0, buffer.length);
+ buffer = b;
+ }
+ }
+
+ /**
+ * Ensure that the buffer has room for <code>size</code> bytes
+ *
+ * @param size minimum spare space required
+ */
+ protected void ensureBufferSize(int size){
+ if ((buffer == null) || (buffer.length < pos + size)){
+ resizeBuffer();
+ }
+ }
+
+ /**
+ * Extracts buffered data into the provided byte[] array, starting at position bPos,
+ * up to a maximum of bAvail bytes. Returns how many bytes were actually extracted.
+ *
+ * @param b
+ * byte[] array to extract the buffered data into.
+ * @param bPos
+ * position in byte[] array to start extraction at.
+ * @param bAvail
+ * amount of bytes we're allowed to extract. We may extract fewer (if fewer are available).
+ * @return The number of bytes successfully extracted into the provided byte[] array.
+ */
+ int readResults(byte[] b, int bPos, int bAvail) { // package protected for access from I/O streams
+ if (buffer != null) {
+ int len = Math.min(available(), bAvail);
+ System.arraycopy(buffer, readPos, b, bPos, len);
+ readPos += len;
+ if (readPos >= pos) {
+ buffer = null; // so hasData() will return false, and this method can return -1
+ }
+ return len;
+ }
+ return eof ? -1 : 0;
+ }
+
+ /**
+ * Checks if a byte value is whitespace or not.
+ * Whitespace is taken to mean: space, tab, CR, LF
+ * @param byteToCheck
+ * the byte to check
+ * @return true if byte is whitespace, false otherwise
+ */
+ protected static boolean isWhiteSpace(byte byteToCheck) {
+ switch (byteToCheck) {
+ case ' ' :
+ case '\n' :
+ case '\r' :
+ case '\t' :
+ return true;
+ default :
+ return false;
+ }
+ }
+
+ /**
+ * Resets this object to its initial newly constructed state.
+ */
+ private void reset() {
+ buffer = null;
+ pos = 0;
+ readPos = 0;
+ currentLinePos = 0;
+ modulus = 0;
+ eof = false;
+ }
+
+
+ public static String newStringUtf8(byte[] content) {
+ try {
+ return new String(content, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException("UTF-8 is always supported.");
+ }
+ }
+
+ /**
+ * Decodes a String containing characters in the Base-N alphabet.
+ *
+ * @param pArray
+ * A String containing Base-N character data
+ * @return a byte array containing binary data
+ */
+ public byte[] decode(String pArray) {
+ return decode(getBytesUtf8(pArray));
+ }
+
+ /**
+ * Decodes a byte[] containing characters in the Base-N alphabet.
+ *
+ * @param pArray
+ * A byte array containing Base-N character data
+ * @return a byte array containing binary data
+ */
+ public byte[] decode(byte[] pArray) {
+ reset();
+ if (pArray == null || pArray.length == 0) {
+ return pArray;
+ }
+ decode(pArray, 0, pArray.length);
+ decode(pArray, 0, -1); // Notify decoder of EOF.
+ byte[] result = new byte[pos];
+ readResults(result, 0, result.length);
+ return result;
+ }
+
+ /**
+ * Encodes a byte[] containing binary data, into a byte[] containing characters in the alphabet.
+ *
+ * @param pArray
+ * a byte array containing binary data
+ * @return A byte array containing only the basen alphabetic character data
+ */
+ public byte[] encode(byte[] pArray) {
+ reset();
+ if (pArray == null || pArray.length == 0) {
+ return pArray;
+ }
+ encode(pArray, 0, pArray.length);
+ encode(pArray, 0, -1); // Notify encoder of EOF.
+ byte[] buf = new byte[pos - readPos];
+ readResults(buf, 0, buf.length);
+ return buf;
+ }
+
+ abstract void encode(byte[] pArray, int i, int length); // package protected for access from I/O streams
+
+ abstract void decode(byte[] pArray, int i, int length); // package protected for access from I/O streams
+
+ /**
+ * Returns whether or not the <code>octet</code> is in the current alphabet.
+ * Does not allow whitespace or pad.
+ *
+ * @param value The value to test
+ *
+ * @return <code>true</code> if the value is defined in the current alphabet, <code>false</code> otherwise.
+ */
+ protected abstract boolean isInAlphabet(byte value);
+
+ public static byte[] getBytesUtf8(String content) {
+ if(content == null) {
+ return new byte[0];
+ }
+ try {
+ return content.getBytes("UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException("UTF-8 is always supported.");
+ }
+ }
+
+ /**
+ * Tests a given byte array to see if it contains any characters within the alphabet or PAD.
+ *
+ * Intended for use in checking line-ending arrays
+ *
+ * @param arrayOctet
+ * byte array to test
+ * @return <code>true</code> if any byte is a valid character in the alphabet or PAD; <code>false</code> otherwise
+ */
+ protected boolean containsAlphabetOrPad(byte[] arrayOctet) {
+ if (arrayOctet == null) {
+ return false;
+ }
+ for (byte element : arrayOctet) {
+ if (PAD == element || isInAlphabet(element)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Calculates the amount of space needed to encode the supplied array.
+ *
+ * @param pArray byte[] array which will later be encoded
+ *
+ * @return amount of space needed to encoded the supplied array.
+ * Returns a long since a max-len array will require > Integer.MAX_VALUE
+ */
+ public long getEncodedLength(byte[] pArray) {
+ // Calculate non-chunked size - rounded up to allow for padding
+ // cast to long is needed to avoid possibility of overflow
+ long len = ((pArray.length + unencodedBlockSize-1) / unencodedBlockSize) * (long) encodedBlockSize;
+ if (lineLength > 0) { // We're using chunking
+ // Round up to nearest multiple
+ len += ((len + lineLength-1) / lineLength) * chunkSeparatorLength;
+ }
+ return len;
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb1ba468/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/Hex.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/Hex.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/Hex.java
new file mode 100644
index 0000000..ef640b1
--- /dev/null
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/Hex.java
@@ -0,0 +1,124 @@
+/*
+ * 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.commons;
+
+import java.io.IOException;
+
+/**
+ * Converts hexadecimal Strings.
+ *
+ * @author Apache Software Foundation
+ * @version $Id: Hex.java 1157192 2011-08-12 17:27:38Z ggregory $
+ * @since 1.1
+ */
+public class Hex {
+
+ /**
+ * Used to build output as Hex
+ */
+ private static final char[] DIGITS_LOWER = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
+ 'e', 'f'};
+
+ /**
+ * Used to build output as Hex
+ */
+ private static final char[] DIGITS_UPPER = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
+ 'E', 'F'};
+
+ /**
+ * Converts an array of characters representing hexadecimal values into an array of bytes of those same values. The
+ * returned array will be half the length of the passed array, as it takes two characters to represent any given
+ * byte. An exception is thrown if the passed char array has an odd number of elements.
+ *
+ * @param data An array of characters containing hexadecimal digits
+ * @return A byte array containing binary data decoded from the supplied char array.
+ * @throws IOException Thrown if an odd number or illegal of characters is supplied
+ */
+ public static byte[] decodeHex(char[] data) throws IOException {
+
+ int len = data.length;
+
+ if ((len & 0x01) != 0) {
+ throw new IOException("Odd number of characters.");
+ }
+
+ byte[] out = new byte[len >> 1];
+
+ // two characters form the hex value.
+ for (int i = 0, j = 0; j < len; i++) {
+ int f = toDigit(data[j], j) << 4;
+ j++;
+ f = f | toDigit(data[j], j);
+ j++;
+ out[i] = (byte) (f & 0xFF);
+ }
+
+ return out;
+ }
+
+ /**
+ * Converts an array of bytes into an array of characters representing the hexadecimal values of each byte in order.
+ * The returned array will be double the length of the passed array, as it takes two characters to represent any
+ * given byte.
+ *
+ * @param data a byte[] to convert to Hex characters
+ * @param toLowerCase <code>true</code> converts to lowercase, <code>false</code> to uppercase
+ * @return A char[] containing hexadecimal characters
+ * @since 1.4
+ */
+ public static char[] encodeHex(byte[] data, boolean toLowerCase) {
+ return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
+ }
+
+ /**
+ * Converts an array of bytes into an array of characters representing the hexadecimal values of each byte in order.
+ * The returned array will be double the length of the passed array, as it takes two characters to represent any
+ * given byte.
+ *
+ * @param data a byte[] to convert to Hex characters
+ * @param toDigits the output alphabet
+ * @return A char[] containing hexadecimal characters
+ * @since 1.4
+ */
+ protected static char[] encodeHex(byte[] data, char[] toDigits) {
+ int l = data.length;
+ char[] out = new char[l << 1];
+ // two characters form the hex value.
+ for (int i = 0, j = 0; i < l; i++) {
+ out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
+ out[j++] = toDigits[0x0F & data[i]];
+ }
+ return out;
+ }
+
+ /**
+ * Converts a hexadecimal character to an integer.
+ *
+ * @param ch A character to convert to an integer digit
+ * @param index The index of the character in the source
+ * @return An integer
+ * @throws IOException Thrown if ch is an illegal hex character
+ */
+ protected static int toDigit(char ch, int index) throws IOException {
+ int digit = Character.digit(ch, 16);
+ if (digit == -1) {
+ throw new IOException("Illegal hexadecimal character " + ch + " at index " + index);
+ }
+ return digit;
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb1ba468/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoBody.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoBody.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoBody.java
index 4954c75..696234f 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoBody.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoBody.java
@@ -32,11 +32,11 @@ import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
-import org.apache.commons.codec.binary.Base64;
import org.apache.olingo.odata2.api.commons.HttpContentType;
import org.apache.olingo.odata2.api.ep.EntityProviderException;
import org.apache.olingo.odata2.api.processor.ODataResponse;
import org.apache.olingo.odata2.core.ep.BasicEntityProvider;
+import org.apache.olingo.odata2.core.commons.Base64;
import org.apache.olingo.odata2.core.ep.util.JsonStreamWriter;
import com.google.gson.GsonBuilder;
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb1ba468/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmBinary.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmBinary.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmBinary.java
index 9922cb0..81f86d5 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmBinary.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmBinary.java
@@ -18,12 +18,13 @@
******************************************************************************/
package org.apache.olingo.odata2.core.edm;
-import org.apache.commons.codec.DecoderException;
-import org.apache.commons.codec.binary.Base64;
-import org.apache.commons.codec.binary.Hex;
import org.apache.olingo.odata2.api.edm.EdmFacets;
import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+import org.apache.olingo.odata2.core.commons.Base64;
+import org.apache.olingo.odata2.core.commons.Hex;
+
+import java.io.IOException;
/**
* Implementation of the EDM simple type Binary.
@@ -102,7 +103,7 @@ public class EdmBinary extends AbstractSimpleType {
if (literalKind == EdmLiteralKind.URI) {
try {
result = Hex.decodeHex(value.substring(value.startsWith("X") ? 2 : 7, value.length() - 1).toCharArray());
- } catch (final DecoderException e) {
+ } catch (final IOException e) {
throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value), e);
}
} else {
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb1ba468/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmServiceMetadataImplProv.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmServiceMetadataImplProv.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmServiceMetadataImplProv.java
index 0221dcb..0188741 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmServiceMetadataImplProv.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmServiceMetadataImplProv.java
@@ -18,31 +18,24 @@
******************************************************************************/
package org.apache.olingo.odata2.core.edm.provider;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStreamWriter;
-import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
-import java.util.List;
-
import org.apache.olingo.odata2.api.ODataServiceVersion;
import org.apache.olingo.odata2.api.edm.EdmEntitySetInfo;
import org.apache.olingo.odata2.api.edm.EdmServiceMetadata;
-import org.apache.olingo.odata2.api.edm.provider.DataServices;
-import org.apache.olingo.odata2.api.edm.provider.EdmProvider;
-import org.apache.olingo.odata2.api.edm.provider.EntityContainer;
-import org.apache.olingo.odata2.api.edm.provider.EntitySet;
-import org.apache.olingo.odata2.api.edm.provider.EntityType;
-import org.apache.olingo.odata2.api.edm.provider.Property;
-import org.apache.olingo.odata2.api.edm.provider.Schema;
+import org.apache.olingo.odata2.api.edm.provider.*;
import org.apache.olingo.odata2.api.ep.EntityProviderException;
import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.xml.XMLStreamWriter;
import org.apache.olingo.odata2.core.ep.producer.XmlMetadataProducer;
import org.apache.olingo.odata2.core.ep.util.CircleStreamBuffer;
-import org.apache.olingo.odata2.api.xml.XMLStreamException;
-import org.apache.olingo.odata2.api.xml.XMLStreamWriter;
import org.apache.olingo.odata2.core.xml.XmlStreamFactory;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.List;
+
/**
*
*/
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb1ba468/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/BasicEntityProvider.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/BasicEntityProvider.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/BasicEntityProvider.java
index 8d830f0..85fe7dd 100644
--- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/BasicEntityProvider.java
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/BasicEntityProvider.java
@@ -18,29 +18,11 @@
******************************************************************************/
package org.apache.olingo.odata2.core.ep;
-import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.io.UnsupportedEncodingException;
-import java.nio.charset.Charset;
-import java.util.List;
-import java.util.Map;
-
-import javax.xml.stream.FactoryConfigurationError;
-
import org.apache.olingo.odata2.api.ODataServiceVersion;
import org.apache.olingo.odata2.api.commons.HttpContentType;
import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
import org.apache.olingo.odata2.api.commons.ODataHttpHeaders;
-import org.apache.olingo.odata2.api.edm.EdmException;
-import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
-import org.apache.olingo.odata2.api.edm.EdmProperty;
-import org.apache.olingo.odata2.api.edm.EdmSimpleType;
-import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.edm.*;
import org.apache.olingo.odata2.api.edm.provider.DataServices;
import org.apache.olingo.odata2.api.edm.provider.EntityType;
import org.apache.olingo.odata2.api.edm.provider.Property;
@@ -48,12 +30,17 @@ import org.apache.olingo.odata2.api.edm.provider.Schema;
import org.apache.olingo.odata2.api.ep.EntityProviderException;
import org.apache.olingo.odata2.api.processor.ODataResponse;
import org.apache.olingo.odata2.api.processor.ODataResponse.ODataResponseBuilder;
+import org.apache.olingo.odata2.api.xml.XMLStreamWriter;
import org.apache.olingo.odata2.core.ep.producer.XmlMetadataProducer;
import org.apache.olingo.odata2.core.ep.util.CircleStreamBuffer;
-import org.apache.olingo.odata2.api.xml.XMLStreamException;
-import org.apache.olingo.odata2.api.xml.XMLStreamWriter;
import org.apache.olingo.odata2.core.xml.XmlStreamFactory;
+import javax.xml.stream.FactoryConfigurationError;
+import java.io.*;
+import java.nio.charset.Charset;
+import java.util.List;
+import java.util.Map;
+
/**
* Provider for all basic (content type independent) entity provider methods.
*
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb1ba468/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/debug/DebugInfoBodyTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/debug/DebugInfoBodyTest.java b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/debug/DebugInfoBodyTest.java
index 0d99059..453a220 100644
--- a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/debug/DebugInfoBodyTest.java
+++ b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/debug/DebugInfoBodyTest.java
@@ -27,9 +27,9 @@ import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
-import org.apache.commons.codec.binary.Base64;
import org.apache.olingo.odata2.api.commons.HttpContentType;
import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.core.commons.Base64;
import org.apache.olingo.odata2.core.ep.util.JsonStreamWriter;
import org.junit.Test;
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb1ba468/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/uri/expression/TestTokenizer.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/uri/expression/TestTokenizer.java b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/uri/expression/TestTokenizer.java
index 5be6fc3..560420b 100644
--- a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/uri/expression/TestTokenizer.java
+++ b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/uri/expression/TestTokenizer.java
@@ -20,11 +20,12 @@ package org.apache.olingo.odata2.core.uri.expression;
import static org.junit.Assert.fail;
-import org.apache.commons.codec.DecoderException;
-import org.apache.commons.codec.binary.Base64;
-import org.apache.commons.codec.binary.Hex;
+import org.apache.olingo.odata2.core.commons.Base64;
+import org.apache.olingo.odata2.core.commons.Hex;
import org.junit.Test;
+import java.io.IOException;
+
public class TestTokenizer {
@Test
@@ -73,7 +74,7 @@ public class TestTokenizer {
try {
bArr = Hex.decodeHex(hex.toCharArray());
base64 = Base64.encodeBase64String(bArr);
- } catch (DecoderException e) {
+ } catch (IOException e) {
fail("Error in Unittest preparation ( HEX->base64");
}
return base64;
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb1ba468/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/xml/JavaxStaxStreamFactoryTest.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/xml/JavaxStaxStreamFactoryTest.java b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/xml/JavaxStaxStreamFactoryTest.java
index ba93731..c12ef69 100644
--- a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/xml/JavaxStaxStreamFactoryTest.java
+++ b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/xml/JavaxStaxStreamFactoryTest.java
@@ -20,29 +20,22 @@ package org.apache.olingo.odata2.core.xml;
import junit.framework.Assert;
import org.apache.olingo.odata2.api.edm.Edm;
-import org.apache.olingo.odata2.api.edm.EdmEntitySet;
-import org.apache.olingo.odata2.api.ep.EntityProvider;
import org.apache.olingo.odata2.api.ep.EntityProviderException;
-import org.apache.olingo.odata2.api.ep.EntityProviderReadProperties;
-import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
-import org.apache.olingo.odata2.api.xml.XMLStreamConstants;
-import org.apache.olingo.odata2.api.xml.XMLStreamException;
import org.apache.olingo.odata2.api.xml.XMLStreamReader;
import org.apache.olingo.odata2.api.xml.XMLStreamWriter;
import org.apache.olingo.odata2.core.ep.AbstractXmlProducerTestHelper;
import org.apache.olingo.odata2.testutil.helper.StringHelper;
-import org.apache.olingo.odata2.testutil.mock.MockFacade;
import org.custommonkey.xmlunit.SimpleNamespaceContext;
import org.custommonkey.xmlunit.XMLUnit;
import org.junit.Before;
import org.junit.Test;
-import java.io.*;
-import java.util.Calendar;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
-import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static org.apache.olingo.odata2.api.xml.XMLStreamReaderFactory.XML_STREAM_READER_FACTORY_CLASS;
import static org.apache.olingo.odata2.api.xml.XMLStreamWriterFactory.XML_STREAM_WRITER_FACTORY_CLASS;
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb1ba468/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 910d2de..3460f2b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -60,7 +60,6 @@
<httpcore.version>4.2.3</httpcore.version>
<slf4j.version>1.7.1</slf4j.version>
<log4j.version>1.2.17</log4j.version>
- <commonscodec.version>1.6</commonscodec.version>
<commonslang.version>3.1</commonslang.version>
<gson.version>2.2.2</gson.version>
[3/6] [OLINGO-231] Several refactorings
Posted by mi...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb1ba468/odata2-android/src/test/resources/LargeEmployeeFeed.xml
----------------------------------------------------------------------
diff --git a/odata2-android/src/test/resources/LargeEmployeeFeed.xml b/odata2-android/src/test/resources/LargeEmployeeFeed.xml
new file mode 100644
index 0000000..e9b58d9
--- /dev/null
+++ b/odata2-android/src/test/resources/LargeEmployeeFeed.xml
@@ -0,0 +1,12556 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!--
+ 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.
+ -->
+<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="https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/">
+ <id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees</id>
+ <title type="text">Employees</title>
+ <updated>2013-12-02T12:20:28.605Z</updated>
+ <author>
+ <name/>
+ </author>
+ <link href="Employees" rel="self" title="Employees"/>
+ <entry>
+ <id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('1')</id>
+ <title type="text">Walter Winter</title>
+ <updated>1999-01-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+ <link href="Employees('1')" rel="edit" title="Employee"/>
+ <link href="Employees('1')/$value" rel="edit-media" type="image/jpeg"/>
+ <link href="Employees('1')/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('1')/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('1')/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="image/jpeg" src="Employees('1')/$value"/>
+ <m:properties>
+ <d:EmployeeId>1</d:EmployeeId>
+ <d:EmployeeName>Walter Winter</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>1</d:RoomId>
+ <d:TeamId>1</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69124</d:PostalCode>
+ <d:CityName>Heidelberg</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>52</d:Age>
+ <d:EntryDate>1999-01-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('1')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.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="image/jpeg"/>
+ <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="image/jpeg" 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>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('3')</id>
+ <title type="text">Jonathan Smith</title>
+ <updated>2013-12-02T12:20:28.622Z</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="image/jpeg"/>
+ <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="image/jpeg" 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>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.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="image/jpeg"/>
+ <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="image/jpeg" 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>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('5')</id>
+ <title type="text">John Field</title>
+ <updated>2001-02-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+ <link href="Employees('5')" rel="edit" title="Employee"/>
+ <link href="Employees('5')/$value" rel="edit-media" type="image/jpeg"/>
+ <link href="Employees('5')/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('5')/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('5')/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="image/jpeg" src="Employees('5')/$value"/>
+ <m:properties>
+ <d:EmployeeId>5</d:EmployeeId>
+ <d:EmployeeName>John Field</d:EmployeeName>
+ <d:ManagerId>3</d:ManagerId>
+ <d:RoomId>3</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>42</d:Age>
+ <d:EntryDate>2001-02-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('5')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.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="image/jpeg"/>
+ <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="image/jpeg" 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>
+ <entry>
+ <id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('1')</id>
+ <title type="text">Walter Winter</title>
+ <updated>1999-01-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+ <link href="Employees('1')" rel="edit" title="Employee"/>
+ <link href="Employees('1')/$value" rel="edit-media" type="image/jpeg"/>
+ <link href="Employees('1')/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('1')/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('1')/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="image/jpeg" src="Employees('1')/$value"/>
+ <m:properties>
+ <d:EmployeeId>1</d:EmployeeId>
+ <d:EmployeeName>Walter Winter</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>1</d:RoomId>
+ <d:TeamId>1</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69124</d:PostalCode>
+ <d:CityName>Heidelberg</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>52</d:Age>
+ <d:EntryDate>1999-01-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('1')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.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="image/jpeg"/>
+ <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="image/jpeg" 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>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('3')</id>
+ <title type="text">Jonathan Smith</title>
+ <updated>2013-12-02T12:20:28.622Z</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="image/jpeg"/>
+ <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="image/jpeg" 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>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.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="image/jpeg"/>
+ <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="image/jpeg" 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>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('5')</id>
+ <title type="text">John Field</title>
+ <updated>2001-02-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+ <link href="Employees('5')" rel="edit" title="Employee"/>
+ <link href="Employees('5')/$value" rel="edit-media" type="image/jpeg"/>
+ <link href="Employees('5')/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('5')/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('5')/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="image/jpeg" src="Employees('5')/$value"/>
+ <m:properties>
+ <d:EmployeeId>5</d:EmployeeId>
+ <d:EmployeeName>John Field</d:EmployeeName>
+ <d:ManagerId>3</d:ManagerId>
+ <d:RoomId>3</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>42</d:Age>
+ <d:EntryDate>2001-02-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('5')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.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="image/jpeg"/>
+ <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="image/jpeg" 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>
+ <entry>
+ <id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('1')</id>
+ <title type="text">Walter Winter</title>
+ <updated>1999-01-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+ <link href="Employees('1')" rel="edit" title="Employee"/>
+ <link href="Employees('1')/$value" rel="edit-media" type="image/jpeg"/>
+ <link href="Employees('1')/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('1')/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('1')/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="image/jpeg" src="Employees('1')/$value"/>
+ <m:properties>
+ <d:EmployeeId>1</d:EmployeeId>
+ <d:EmployeeName>Walter Winter</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>1</d:RoomId>
+ <d:TeamId>1</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69124</d:PostalCode>
+ <d:CityName>Heidelberg</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>52</d:Age>
+ <d:EntryDate>1999-01-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('1')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.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="image/jpeg"/>
+ <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="image/jpeg" 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>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('3')</id>
+ <title type="text">Jonathan Smith</title>
+ <updated>2013-12-02T12:20:28.622Z</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="image/jpeg"/>
+ <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="image/jpeg" 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>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.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="image/jpeg"/>
+ <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="image/jpeg" 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>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('5')</id>
+ <title type="text">John Field</title>
+ <updated>2001-02-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+ <link href="Employees('5')" rel="edit" title="Employee"/>
+ <link href="Employees('5')/$value" rel="edit-media" type="image/jpeg"/>
+ <link href="Employees('5')/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('5')/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('5')/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="image/jpeg" src="Employees('5')/$value"/>
+ <m:properties>
+ <d:EmployeeId>5</d:EmployeeId>
+ <d:EmployeeName>John Field</d:EmployeeName>
+ <d:ManagerId>3</d:ManagerId>
+ <d:RoomId>3</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>42</d:Age>
+ <d:EntryDate>2001-02-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('5')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.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="image/jpeg"/>
+ <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="image/jpeg" 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>
+ <entry>
+ <id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('1')</id>
+ <title type="text">Walter Winter</title>
+ <updated>1999-01-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+ <link href="Employees('1')" rel="edit" title="Employee"/>
+ <link href="Employees('1')/$value" rel="edit-media" type="image/jpeg"/>
+ <link href="Employees('1')/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('1')/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('1')/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="image/jpeg" src="Employees('1')/$value"/>
+ <m:properties>
+ <d:EmployeeId>1</d:EmployeeId>
+ <d:EmployeeName>Walter Winter</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>1</d:RoomId>
+ <d:TeamId>1</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69124</d:PostalCode>
+ <d:CityName>Heidelberg</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>52</d:Age>
+ <d:EntryDate>1999-01-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('1')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.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="image/jpeg"/>
+ <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="image/jpeg" 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>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('3')</id>
+ <title type="text">Jonathan Smith</title>
+ <updated>2013-12-02T12:20:28.622Z</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="image/jpeg"/>
+ <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="image/jpeg" 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>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.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="image/jpeg"/>
+ <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="image/jpeg" 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>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('5')</id>
+ <title type="text">John Field</title>
+ <updated>2001-02-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+ <link href="Employees('5')" rel="edit" title="Employee"/>
+ <link href="Employees('5')/$value" rel="edit-media" type="image/jpeg"/>
+ <link href="Employees('5')/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('5')/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('5')/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="image/jpeg" src="Employees('5')/$value"/>
+ <m:properties>
+ <d:EmployeeId>5</d:EmployeeId>
+ <d:EmployeeName>John Field</d:EmployeeName>
+ <d:ManagerId>3</d:ManagerId>
+ <d:RoomId>3</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>42</d:Age>
+ <d:EntryDate>2001-02-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('5')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.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="image/jpeg"/>
+ <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="image/jpeg" 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>
+ <entry>
+ <id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('1')</id>
+ <title type="text">Walter Winter</title>
+ <updated>1999-01-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+ <link href="Employees('1')" rel="edit" title="Employee"/>
+ <link href="Employees('1')/$value" rel="edit-media" type="image/jpeg"/>
+ <link href="Employees('1')/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('1')/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('1')/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="image/jpeg" src="Employees('1')/$value"/>
+ <m:properties>
+ <d:EmployeeId>1</d:EmployeeId>
+ <d:EmployeeName>Walter Winter</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>1</d:RoomId>
+ <d:TeamId>1</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69124</d:PostalCode>
+ <d:CityName>Heidelberg</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>52</d:Age>
+ <d:EntryDate>1999-01-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('1')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.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="image/jpeg"/>
+ <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="image/jpeg" 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>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('3')</id>
+ <title type="text">Jonathan Smith</title>
+ <updated>2013-12-02T12:20:28.622Z</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="image/jpeg"/>
+ <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="image/jpeg" 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>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.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="image/jpeg"/>
+ <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="image/jpeg" 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>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('5')</id>
+ <title type="text">John Field</title>
+ <updated>2001-02-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+ <link href="Employees('5')" rel="edit" title="Employee"/>
+ <link href="Employees('5')/$value" rel="edit-media" type="image/jpeg"/>
+ <link href="Employees('5')/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('5')/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('5')/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="image/jpeg" src="Employees('5')/$value"/>
+ <m:properties>
+ <d:EmployeeId>5</d:EmployeeId>
+ <d:EmployeeName>John Field</d:EmployeeName>
+ <d:ManagerId>3</d:ManagerId>
+ <d:RoomId>3</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>42</d:Age>
+ <d:EntryDate>2001-02-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('5')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.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="image/jpeg"/>
+ <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="image/jpeg" 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>
+ <entry>
+ <id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('1')</id>
+ <title type="text">Walter Winter</title>
+ <updated>1999-01-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+ <link href="Employees('1')" rel="edit" title="Employee"/>
+ <link href="Employees('1')/$value" rel="edit-media" type="image/jpeg"/>
+ <link href="Employees('1')/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('1')/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('1')/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="image/jpeg" src="Employees('1')/$value"/>
+ <m:properties>
+ <d:EmployeeId>1</d:EmployeeId>
+ <d:EmployeeName>Walter Winter</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>1</d:RoomId>
+ <d:TeamId>1</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69124</d:PostalCode>
+ <d:CityName>Heidelberg</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>52</d:Age>
+ <d:EntryDate>1999-01-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('1')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.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="image/jpeg"/>
+ <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="image/jpeg" 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>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('3')</id>
+ <title type="text">Jonathan Smith</title>
+ <updated>2013-12-02T12:20:28.622Z</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="image/jpeg"/>
+ <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="image/jpeg" 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>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.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="image/jpeg"/>
+ <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="image/jpeg" 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>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('5')</id>
+ <title type="text">John Field</title>
+ <updated>2001-02-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+ <link href="Employees('5')" rel="edit" title="Employee"/>
+ <link href="Employees('5')/$value" rel="edit-media" type="image/jpeg"/>
+ <link href="Employees('5')/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('5')/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('5')/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="image/jpeg" src="Employees('5')/$value"/>
+ <m:properties>
+ <d:EmployeeId>5</d:EmployeeId>
+ <d:EmployeeName>John Field</d:EmployeeName>
+ <d:ManagerId>3</d:ManagerId>
+ <d:RoomId>3</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>42</d:Age>
+ <d:EntryDate>2001-02-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('5')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.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="image/jpeg"/>
+ <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="image/jpeg" 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>
+ <entry>
+ <id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('1')</id>
+ <title type="text">Walter Winter</title>
+ <updated>1999-01-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+ <link href="Employees('1')" rel="edit" title="Employee"/>
+ <link href="Employees('1')/$value" rel="edit-media" type="image/jpeg"/>
+ <link href="Employees('1')/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('1')/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('1')/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="image/jpeg" src="Employees('1')/$value"/>
+ <m:properties>
+ <d:EmployeeId>1</d:EmployeeId>
+ <d:EmployeeName>Walter Winter</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>1</d:RoomId>
+ <d:TeamId>1</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69124</d:PostalCode>
+ <d:CityName>Heidelberg</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>52</d:Age>
+ <d:EntryDate>1999-01-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('1')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.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="image/jpeg"/>
+ <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="image/jpeg" 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>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('3')</id>
+ <title type="text">Jonathan Smith</title>
+ <updated>2013-12-02T12:20:28.622Z</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="image/jpeg"/>
+ <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="image/jpeg" 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>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.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="image/jpeg"/>
+ <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="image/jpeg" 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>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('5')</id>
+ <title type="text">John Field</title>
+ <updated>2001-02-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+ <link href="Employees('5')" rel="edit" title="Employee"/>
+ <link href="Employees('5')/$value" rel="edit-media" type="image/jpeg"/>
+ <link href="Employees('5')/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('5')/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('5')/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="image/jpeg" src="Employees('5')/$value"/>
+ <m:properties>
+ <d:EmployeeId>5</d:EmployeeId>
+ <d:EmployeeName>John Field</d:EmployeeName>
+ <d:ManagerId>3</d:ManagerId>
+ <d:RoomId>3</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>42</d:Age>
+ <d:EntryDate>2001-02-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('5')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.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="image/jpeg"/>
+ <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="image/jpeg" 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>
+ <entry>
+ <id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('1')</id>
+ <title type="text">Walter Winter</title>
+ <updated>1999-01-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+ <link href="Employees('1')" rel="edit" title="Employee"/>
+ <link href="Employees('1')/$value" rel="edit-media" type="image/jpeg"/>
+ <link href="Employees('1')/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('1')/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('1')/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="image/jpeg" src="Employees('1')/$value"/>
+ <m:properties>
+ <d:EmployeeId>1</d:EmployeeId>
+ <d:EmployeeName>Walter Winter</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>1</d:RoomId>
+ <d:TeamId>1</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69124</d:PostalCode>
+ <d:CityName>Heidelberg</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>52</d:Age>
+ <d:EntryDate>1999-01-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('1')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.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="image/jpeg"/>
+ <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="image/jpeg" 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>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('3')</id>
+ <title type="text">Jonathan Smith</title>
+ <updated>2013-12-02T12:20:28.622Z</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="image/jpeg"/>
+ <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="image/jpeg" 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>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.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="image/jpeg"/>
+ <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="image/jpeg" 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>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('5')</id>
+ <title type="text">John Field</title>
+ <updated>2001-02-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+ <link href="Employees('5')" rel="edit" title="Employee"/>
+ <link href="Employees('5')/$value" rel="edit-media" type="image/jpeg"/>
+ <link href="Employees('5')/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('5')/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('5')/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="image/jpeg" src="Employees('5')/$value"/>
+ <m:properties>
+ <d:EmployeeId>5</d:EmployeeId>
+ <d:EmployeeName>John Field</d:EmployeeName>
+ <d:ManagerId>3</d:ManagerId>
+ <d:RoomId>3</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>42</d:Age>
+ <d:EntryDate>2001-02-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('5')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.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="image/jpeg"/>
+ <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="image/jpeg" 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>
+ <entry>
+ <id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('1')</id>
+ <title type="text">Walter Winter</title>
+ <updated>1999-01-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+ <link href="Employees('1')" rel="edit" title="Employee"/>
+ <link href="Employees('1')/$value" rel="edit-media" type="image/jpeg"/>
+ <link href="Employees('1')/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('1')/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('1')/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="image/jpeg" src="Employees('1')/$value"/>
+ <m:properties>
+ <d:EmployeeId>1</d:EmployeeId>
+ <d:EmployeeName>Walter Winter</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>1</d:RoomId>
+ <d:TeamId>1</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69124</d:PostalCode>
+ <d:CityName>Heidelberg</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>52</d:Age>
+ <d:EntryDate>1999-01-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('1')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.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="image/jpeg"/>
+ <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="image/jpeg" 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>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('3')</id>
+ <title type="text">Jonathan Smith</title>
+ <updated>2013-12-02T12:20:28.622Z</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="image/jpeg"/>
+ <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="image/jpeg" 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>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.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="image/jpeg"/>
+ <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="image/jpeg" 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>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Employees('5')</id>
+ <title type="text">John Field</title>
+ <updated>2001-02-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+ <link href="Employees('5')" rel="edit" title="Employee"/>
+ <link href="Employees('5')/$value" rel="edit-media" type="image/jpeg"/>
+ <link href="Employees('5')/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('5')/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('5')/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="image/jpeg" src="Employees('5')/$value"/>
+ <m:properties>
+ <d:EmployeeId>5</d:EmployeeId>
+ <d:EmployeeName>John Field</d:EmployeeName>
+ <d:ManagerId>3</d:ManagerId>
+ <d:RoomId>3</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>42</d:Age>
+ <d:EntryDate>2001-02-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('5')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.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="image/jpeg"/>
+ <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="image/jpeg" 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>
+ <entry>
+ <id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/Referenc
<TRUNCATED>
[4/6] [OLINGO-231] Several refactorings
Posted by mi...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb1ba468/odata2-android/src/test/java/org/apache/olingo/odata2/android/xml/XmlFeedConsumerTest.java
----------------------------------------------------------------------
diff --git a/odata2-android/src/test/java/org/apache/olingo/odata2/android/xml/XmlFeedConsumerTest.java b/odata2-android/src/test/java/org/apache/olingo/odata2/android/xml/XmlFeedConsumerTest.java
new file mode 100644
index 0000000..151b8b9
--- /dev/null
+++ b/odata2-android/src/test/java/org/apache/olingo/odata2/android/xml/XmlFeedConsumerTest.java
@@ -0,0 +1,155 @@
+/*******************************************************************************
+ * 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.android.xml;
+
+import junit.framework.Assert;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.ep.EntityProvider;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.EntityProviderReadProperties;
+import org.apache.olingo.odata2.api.ep.feed.FeedMetadata;
+import org.apache.olingo.odata2.api.ep.feed.ODataDeltaFeed;
+import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
+import org.apache.olingo.odata2.core.ep.consumer.XmlEntityConsumer;
+import org.apache.olingo.odata2.testutil.mock.MockFacade;
+import org.junit.Test;
+import org.robolectric.annotation.Config;
+
+import java.io.InputStream;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+@Config(manifest=Config.NONE)
+public class XmlFeedConsumerTest extends AndroidTestBase {
+
+ @Test
+ public void readLargeEmployeesFeed() throws Exception {
+ InputStream file = getFileAsStream("LargeEmployeeFeed.xml");
+ assertNotNull(file);
+
+ EntityProviderReadProperties properties = EntityProviderReadProperties.init().build();
+ ODataFeed feed =
+ EntityProvider.readFeed("application/atom+xml", MockFacade.getMockEdm().getDefaultEntityContainer()
+ .getEntitySet(
+ "Employees"), file, properties);
+ assertNotNull(feed);
+
+ FeedMetadata feedMetadata = feed.getFeedMetadata();
+ assertNotNull(feedMetadata);
+ }
+
+ @Test
+ public void readEmployeesFeedWithInlineCountValid() throws Exception {
+ // prepare
+ String content = readFile("feed_employees_full.xml");
+ assertNotNull(content);
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+ InputStream reqContent = createContentAsStream(content);
+
+ // execute
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ EntityProviderReadProperties consumerProperties = EntityProviderReadProperties.init()
+ .mergeSemantic(false).build();
+
+ ODataFeed feed = xec.readFeed(entitySet, reqContent, consumerProperties);
+ assertNotNull(feed);
+
+ FeedMetadata feedMetadata = feed.getFeedMetadata();
+ assertNotNull(feedMetadata);
+
+ int inlineCount = feedMetadata.getInlineCount();
+ // Null means no inlineCount found
+ assertNotNull(inlineCount);
+
+ assertEquals(6, inlineCount);
+ }
+
+ @Test(expected = EntityProviderException.class)
+ public void readEmployeesFeedWithInlineCountNegative() throws Exception {
+ // prepare
+ String content = readFile("feed_employees_full.xml").replace("<m:count>6</m:count>", "<m:count>-1</m:count>");
+ assertNotNull(content);
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+ InputStream reqContent = createContentAsStream(content);
+
+ // execute
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ EntityProviderReadProperties consumerProperties = EntityProviderReadProperties.init()
+ .mergeSemantic(false).build();
+
+ try {
+ xec.readFeed(entitySet, reqContent, consumerProperties);
+ } catch (EntityProviderException e) {
+ assertEquals(EntityProviderException.INLINECOUNT_INVALID, e.getMessageReference());
+ throw e;
+ }
+
+ Assert.fail("Exception expected");
+ }
+
+ @Test(expected = EntityProviderException.class)
+ public void readEmployeesFeedWithInlineCountLetters() throws Exception {
+ // prepare
+ String content = readFile("feed_employees_full.xml").replace("<m:count>6</m:count>", "<m:count>AAA</m:count>");
+ assertNotNull(content);
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+ InputStream reqContent = createContentAsStream(content);
+
+ // execute
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ EntityProviderReadProperties consumerProperties = EntityProviderReadProperties.init()
+ .mergeSemantic(false).build();
+
+ try {
+ xec.readFeed(entitySet, reqContent, consumerProperties);
+ } catch (EntityProviderException e) {
+ assertEquals(EntityProviderException.INLINECOUNT_INVALID, e.getMessageReference());
+ throw e;
+ }
+
+ Assert.fail("Exception expected");
+ }
+
+ @Test
+ public void readDeltaFeed() throws Exception {
+ // prepare
+ String content = readFile("feed_with_deleted_entries.xml");
+ assertNotNull(content);
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+ InputStream reqContent = createContentAsStream(content);
+
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ EntityProviderReadProperties consumerProperties = EntityProviderReadProperties.init().build();
+
+ ODataDeltaFeed deltaFeed = xec.readFeed(entitySet, reqContent, consumerProperties);
+
+ assertNotNull(deltaFeed);
+
+ assertNotNull(deltaFeed.getDeletedEntries());
+ assertNotNull(deltaFeed.getEntries());
+
+ assertEquals(1, deltaFeed.getEntries().size());
+ assertEquals(1, deltaFeed.getDeletedEntries().size());
+ }
+}
[5/6] [OLINGO-231] Several refactorings
Posted by mi...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb1ba468/odata2-android/src/test/java/org/apache/olingo/odata2/android/xml/XmlEntityConsumerTest.java
----------------------------------------------------------------------
diff --git a/odata2-android/src/test/java/org/apache/olingo/odata2/android/xml/XmlEntityConsumerTest.java b/odata2-android/src/test/java/org/apache/olingo/odata2/android/xml/XmlEntityConsumerTest.java
new file mode 100644
index 0000000..fbaa71b
--- /dev/null
+++ b/odata2-android/src/test/java/org/apache/olingo/odata2/android/xml/XmlEntityConsumerTest.java
@@ -0,0 +1,2420 @@
+/*******************************************************************************
+ * 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.android.xml;
+
+import org.apache.olingo.odata2.api.commons.HttpContentType;
+import org.apache.olingo.odata2.api.edm.*;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.EntityProviderReadProperties;
+import org.apache.olingo.odata2.api.ep.callback.OnReadInlineContent;
+import org.apache.olingo.odata2.api.ep.callback.ReadEntryResult;
+import org.apache.olingo.odata2.api.ep.callback.ReadFeedResult;
+import org.apache.olingo.odata2.api.ep.callback.ReadResult;
+import org.apache.olingo.odata2.api.ep.entry.EntryMetadata;
+import org.apache.olingo.odata2.api.ep.entry.MediaMetadata;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.api.ep.feed.FeedMetadata;
+import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
+import org.apache.olingo.odata2.api.exception.MessageReference;
+import org.apache.olingo.odata2.api.exception.ODataMessageException;
+import org.apache.olingo.odata2.api.uri.ExpandSelectTreeNode;
+import org.apache.olingo.odata2.core.ep.consumer.XmlEntityConsumer;
+import org.apache.olingo.odata2.testutil.helper.StringHelper;
+import org.apache.olingo.odata2.testutil.mock.MockFacade;
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.robolectric.annotation.Config;
+
+import java.io.InputStream;
+import java.util.*;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import static org.junit.Assert.*;
+
+/**
+ *
+ */
+@Config(manifest=Config.NONE)
+public class XmlEntityConsumerTest extends AndroidTestBase {
+
+ private static final Logger LOG = Logger.getLogger(XmlEntityConsumerTest.class.getName());
+ static {
+ LOG.setLevel(Level.OFF);
+ }
+
+ public static final String EMPLOYEE_1_XML =
+ "<?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/\" " +
+ "m:etag=\"W/"1"\">"
+ +
+ " <id>http://localhost:19000/Employees('1')</id>"
+ +
+ " <title type=\"text\">Walter Winter</title>"
+ +
+ " <updated>1999-01-01T00:00:00Z</updated>"
+ +
+ " <category term=\"RefScenario.Employee\" " +
+ "scheme=\"http://schemas.microsoft.com/ado/2007/08/dataservices/scheme\"/>"
+ +
+ " <link href=\"Employees('1')\" rel=\"edit\" title=\"Employee\"/>"
+ +
+ " <link href=\"Employees('1')/$value\" rel=\"edit-media\" " +
+ "type=\"application/octet-stream\" m:etag=\"mmEtag\"/>"
+ +
+ " <link href=\"Employees('1')/ne_Room\" " +
+ "rel=\"http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room\" " +
+ "type=\"application/atom+xml; type=entry\" title=\"ne_Room\"/>"
+ +
+ " <link href=\"Employees('1')/ne_Manager\" " +
+ "rel=\"http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager\" " +
+ "type=\"application/atom+xml; type=entry\" title=\"ne_Manager\"/>"
+ +
+ " <link href=\"Employees('1')/ne_Team\" " +
+ "rel=\"http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team\" " +
+ "type=\"application/atom+xml; type=entry\" title=\"ne_Team\"/>"
+ +
+ " <content type=\"application/octet-stream\" src=\"Employees('1')/$value\"/>" +
+ " <m:properties>" +
+ " <d:EmployeeId>1</d:EmployeeId>" +
+ " <d:EmployeeName>Walter Winter</d:EmployeeName>" +
+ " <d:ManagerId>1</d:ManagerId>" +
+ " <d:RoomId>1</d:RoomId>" +
+ " <d:TeamId>1</d:TeamId>" +
+ " <d:Location m:type=\"RefScenario.c_Location\">" +
+ " <d:Country>Germany</d:Country>" +
+ " <d:City m:type=\"RefScenario.c_City\">" +
+ " <d:PostalCode>69124</d:PostalCode>" +
+ " <d:CityName>Heidelberg</d:CityName>" +
+ " </d:City>" +
+ " </d:Location>" +
+ " <d:Age>52</d:Age>" +
+ " <d:EntryDate>1999-01-01T00:00:00</d:EntryDate>" +
+ " <d:ImageUrl>/SAP/PUBLIC/BC/NWDEMO_MODEL/IMAGES/Employee_1.png</d:ImageUrl>" +
+ " </m:properties>" +
+ "</entry>";
+
+ public static final String EMPLOYEE_1_ROOM_XML =
+ "<?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/\" " +
+ "m:etag=\"W/"1"\">"
+ +
+ " <id>http://localhost:19000/Employees('1')</id>"
+ +
+ " <title type=\"text\">Walter Winter</title>"
+ +
+ " <updated>1999-01-01T00:00:00Z</updated>"
+ +
+ " <category term=\"RefScenario.Employee\" " +
+ "scheme=\"http://schemas.microsoft.com/ado/2007/08/dataservices/scheme\"/>"
+ +
+ " <link href=\"Employees('1')\" rel=\"edit\" title=\"Employee\"/>"
+ +
+ " <link href=\"Employees('1')/$value\" rel=\"edit-media\" type=\"application/octet-stream\" " +
+ "m:etag=\"mmEtag\"/>"
+ +
+ " <link href=\"Employees('1')/ne_Room\" "
+ +
+ " rel=\"http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room\" "
+ +
+ " type=\"application/atom+xml; type=entry\" title=\"ne_Room\">"
+ +
+ " <m:inline>"
+ +
+ " <entry m:etag=\"W/1\" xml:base=\"http://some.host.com/service.root/\">"
+ +
+ " <id>http://some.host.com/service.root/Rooms('1')</id><title " +
+ "type=\"text\">Room 1</title><updated>2013-04-10T10:19:12Z</updated>"
+ +
+ " <content type=\"application/xml\">" +
+ " <m:properties>" +
+ " <d:Id>1</d:Id>" +
+ " <d:Name>Room 1</d:Name>" +
+ " <d:Seats>1</d:Seats>" +
+ " <d:Version>1</d:Version>" +
+ " </m:properties>" +
+ " </content>" +
+ " </entry>" +
+ " </m:inline>" +
+ " </link>" +
+ " <content type=\"application/octet-stream\" src=\"Employees('1')/$value\"/>" +
+ " <m:properties>" +
+ " <d:EmployeeId>1</d:EmployeeId>" +
+ " <d:EmployeeName>Walter Winter</d:EmployeeName>" +
+ " </m:properties>" +
+ "</entry>";
+
+ public static final String EMPLOYEE_1_NULL_ROOM_XML =
+ "<?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/\" " +
+ "m:etag=\"W/"1"\">"
+ +
+ " <id>http://localhost:19000/Employees('1')</id>"
+ +
+ " <title type=\"text\">Walter Winter</title>"
+ +
+ " <updated>1999-01-01T00:00:00Z</updated>"
+ +
+ " <category term=\"RefScenario.Employee\" " +
+ "scheme=\"http://schemas.microsoft.com/ado/2007/08/dataservices/scheme\"/>"
+ +
+ " <link href=\"Employees('1')\" rel=\"edit\" title=\"Employee\"/>"
+ +
+ " <link href=\"Employees('1')/$value\" rel=\"edit-media\" type=\"application/octet-stream\" " +
+ "m:etag=\"mmEtag\"/>"
+ +
+ " <link href=\"Employees('1')/ne_Room\" " +
+ " rel=\"http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room\" " +
+ " type=\"application/atom+xml; type=entry\" title=\"ne_Room\">" +
+ " <m:inline/>" +
+ " </link>" +
+ " <content type=\"application/octet-stream\" src=\"Employees('1')/$value\"/>" +
+ " <m:properties>" +
+ " <d:EmployeeId>1</d:EmployeeId>" +
+ " <d:EmployeeName>Walter Winter</d:EmployeeName>" +
+ " </m:properties>" +
+ "</entry>";
+
+ private static final String ROOM_1_XML =
+ "<?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/test/\" m:etag=\"W/"1"\">"
+ +
+ " <id>http://localhost:19000/test/Rooms('1')</id>"
+ +
+ " <title type=\"text\">Room 1</title>"
+ +
+ " <updated>2013-01-11T13:50:50.541+01:00</updated>"
+ +
+ " <category term=\"RefScenario.Room\" " +
+ "scheme=\"http://schemas.microsoft.com/ado/2007/08/dataservices/scheme\"/>"
+ +
+ " <link href=\"Rooms('1')\" rel=\"edit\" title=\"Room\"/>"
+ +
+ " <link href=\"Rooms('1')/nr_Employees\" " +
+ "rel=\"http://schemas.microsoft.com/ado/2007/08/dataservices/related/nr_Employees\" " +
+ "type=\"application/atom+xml; type=feed\" title=\"nr_Employees\"/>"
+ +
+ " <link href=\"Rooms('1')/nr_Building\" " +
+ "rel=\"http://schemas.microsoft.com/ado/2007/08/dataservices/related/nr_Building\" " +
+ "type=\"application/atom+xml; type=entry\" title=\"nr_Building\"/>"
+ +
+ " <content type=\"application/xml\">" +
+ " <m:properties>" +
+ " <d:Id>1</d:Id>" +
+ " </m:properties>" +
+ " </content>" +
+ "</entry>";
+
+ private static final String ROOM_1_NULL_EMPLOYEE_XML =
+ "<?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/test/\" m:etag=\"W/"1"\">"
+ +
+ " <id>http://localhost:19000/test/Rooms('1')</id>"
+ +
+ " <title type=\"text\">Room 1</title>"
+ +
+ " <updated>2013-01-11T13:50:50.541+01:00</updated>"
+ +
+ " <category term=\"RefScenario.Room\" " +
+ "scheme=\"http://schemas.microsoft.com/ado/2007/08/dataservices/scheme\"/>"
+ +
+ " <link href=\"Rooms('1')\" rel=\"edit\" title=\"Room\"/>"
+ +
+ " <link href=\"Rooms('1')/nr_Employees\" " +
+ "rel=\"http://schemas.microsoft.com/ado/2007/08/dataservices/related/nr_Employees\" "
+ +
+ " type=\"application/atom+xml; type=feed\" title=\"nr_Employees\">"
+ +
+ " <m:inline/> </link> "
+ +
+ " <link href=\"Rooms('1')/nr_Building\" " +
+ "rel=\"http://schemas.microsoft.com/ado/2007/08/dataservices/related/nr_Building\" " +
+ "type=\"application/atom+xml; type=entry\" title=\"nr_Building\"/>"
+ +
+ " <content type=\"application/xml\">" +
+ " <m:properties>" +
+ " <d:Id>1</d:Id>" +
+ " </m:properties>" +
+ " </content>" +
+ "</entry>";
+
+ private static final String PHOTO_XML =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+ +
+ "<entry m:etag=\"W/"1"\" xml:base=\"http://localhost:19000/test\" "
+ +
+ "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\">"
+ +
+ " <id>http://localhost:19000/test/Container2.Photos(Id=1,Type='image%2Fpng')</id>"
+ +
+ " <title type=\"text\">Photo1</title><updated>2013-01-16T12:57:43Z</updated>"
+ +
+ " <category term=\"RefScenario2.Photo\" " +
+ "scheme=\"http://schemas.microsoft.com/ado/2007/08/dataservices/scheme\"/>"
+ +
+ " <link href=\"Container2.Photos(Id=1,Type='image%2Fpng')\" rel=\"edit\" title=\"Photo\"/>" +
+ " <link href=\"Container2.Photos(Id=1,Type='image%2Fpng')/$value\" rel=\"edit-media\" type=\"image/png\"/>" +
+ " <ру:Содержание xmlns:ру=\"http://localhost\">Образ</ру:Содержание>" +
+ " <content type=\"image/png\" src=\"Container2.Photos(Id=1,Type='image%2Fpng')/$value\"/>" +
+ " <m:properties>" +
+ " <d:Id>1</d:Id>" +
+ " <d:Name>Photo1</d:Name>" +
+ " <d:Type>image/png</d:Type>" +
+ " </m:properties>" +
+ "</entry>";
+
+ private static final String PHOTO_XML_INVALID_MAPPING =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+ +
+ "<entry m:etag=\"W/"1"\" xml:base=\"http://localhost:19000/test\" "
+ +
+ "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\">"
+ +
+ " <id>http://localhost:19000/test/Container2.Photos(Id=1,Type='image%2Fpng')</id>"
+ +
+ " <title type=\"text\">Photo1</title><updated>2013-01-16T12:57:43Z</updated>"
+ +
+ " <category term=\"RefScenario2.Photo\" " +
+ "scheme=\"http://schemas.microsoft.com/ado/2007/08/dataservices/scheme\"/>"
+ +
+ " <link href=\"Container2.Photos(Id=1,Type='image%2Fpng')\" rel=\"edit\" title=\"Photo\"/>" +
+ " <link href=\"Container2.Photos(Id=1,Type='image%2Fpng')/$value\" rel=\"edit-media\" type=\"image/png\"/>" +
+ " <ру:Содержание xmlns:ру=\"http://localhost\">Образ</ру:Содержание>" +
+ " <ig:ignore xmlns:ig=\"http://localhost\">ignore</ig:ignore>" + // 406 Bad Request
+ " <content type=\"image/png\" src=\"Container2.Photos(Id=1,Type='image%2Fpng')/$value\"/>" +
+ " <m:properties>" +
+ " <d:Id>1</d:Id>" +
+ " <d:Name>Photo1</d:Name>" +
+ " <d:Type>image/png</d:Type>" +
+ " </m:properties>" +
+ "</entry>";
+
+ private static class EmployeeCallback implements OnReadInlineContent {
+ List<ODataEntry> employees;
+
+ @Override
+ public void handleReadEntry(final ReadEntryResult context) {
+ handleEntry(context);
+ }
+
+ @Override
+ public void handleReadFeed(final ReadFeedResult context) {
+ handleEntry(context);
+ }
+
+ private void handleEntry(final ReadResult context) {
+ try {
+ String navigationPropertyName = context.getNavigationProperty().getName();
+ if (navigationPropertyName.contains("Employees")) {
+ employees = ((ReadFeedResult) context).getResult().getEntries();
+ } else {
+ throw new RuntimeException("Invalid title");
+ }
+ } catch (EdmException e) {
+ throw new RuntimeException("Invalid title");
+ }
+ }
+
+ @Override
+ public EntityProviderReadProperties receiveReadProperties(final EntityProviderReadProperties readProperties,
+ final EdmNavigationProperty navString) {
+ Map<String, Object> typeMappings = new HashMap<String, Object>();
+ typeMappings.put("EmployeeName", String.class);
+ return EntityProviderReadProperties.initFrom(readProperties).addTypeMappings(typeMappings).build();
+ }
+ }
+
+ private static class DefaultCallback implements OnReadInlineContent {
+ private final Map<String, ReadResult> propName2Context = new HashMap<String, ReadResult>();
+
+ @Override
+ public void handleReadEntry(final ReadEntryResult context) {
+ handle(context);
+ }
+
+ @Override
+ public void handleReadFeed(final ReadFeedResult context) {
+ handle(context);
+ }
+
+ private void handle(final ReadResult context) {
+ try {
+ String navigationPropertyName = context.getNavigationProperty().getName();
+ if (navigationPropertyName != null) {
+ propName2Context.put(navigationPropertyName, context);
+ } else {
+ throw new RuntimeException("Invalid title");
+ }
+ } catch (EdmException e) {
+ throw new RuntimeException("Invalid title");
+ }
+ }
+
+ public Object getObject(final String name) {
+ ReadResult context = propName2Context.get(name);
+ if (context == null) {
+ return null;
+ } else {
+ return context.getResult();
+ }
+ }
+
+ public ODataEntry asEntry(final String name) {
+ return (ODataEntry) getObject(name);
+ }
+
+ public ODataFeed asFeed(final String name) {
+ return (ODataFeed) getObject(name);
+ }
+
+ @Override
+ public EntityProviderReadProperties receiveReadProperties(final EntityProviderReadProperties readProperties,
+ final EdmNavigationProperty navigationProperty) {
+ return readProperties;
+ }
+ }
+
+ @Test
+ public void readDeltaLink() throws Exception {
+ // prepare
+ String content = readFile("feed_with_delta_link.xml");
+ assertNotNull(content);
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+ InputStream reqContent = createContentAsStream(content);
+
+ // execute
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ EntityProviderReadProperties consumerProperties = EntityProviderReadProperties.init()
+ .mergeSemantic(false).build();
+
+ ODataFeed feed = xec.readFeed(entitySet, reqContent, consumerProperties);
+ assertNotNull(feed);
+
+ FeedMetadata feedMetadata = feed.getFeedMetadata();
+ assertNotNull(feedMetadata);
+
+ String deltaLink = feedMetadata.getDeltaLink();
+ // Null means no deltaLink found
+ assertNotNull(deltaLink);
+
+ assertEquals("http://thisisadeltalink", deltaLink);
+ }
+
+ /** Teams('1')?$expand=nt_Employees */
+ @Test
+ public void readWithInlineContentAndCallback() throws Exception {
+ // prepare
+ String content = readFile("expanded_team.xml");
+ assertNotNull(content);
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+ InputStream reqContent = createContentAsStream(content);
+
+ // execute
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ EmployeeCallback defaultCallback = new EmployeeCallback();
+ EntityProviderReadProperties consumerProperties = EntityProviderReadProperties.init()
+ .mergeSemantic(false)
+ .callback(defaultCallback)
+ .build();
+
+ ODataEntry entry = xec.readEntry(entitySet, reqContent, consumerProperties);
+ // validate
+ assertNotNull(entry);
+ Map<String, Object> properties = entry.getProperties();
+ assertEquals("1", properties.get("Id"));
+ assertEquals("Team 1", properties.get("Name"));
+ assertEquals(Boolean.FALSE, properties.get("isScrumTeam"));
+ assertNull(properties.get("nt_Employees"));
+ //
+ final List<ODataEntry> employees = defaultCallback.employees;
+ assertEquals(3, employees.size());
+ //
+ ODataEntry employeeNo2 = employees.get(1);
+ Map<String, Object> employessNo2Props = employeeNo2.getProperties();
+ assertEquals("Frederic Fall", employessNo2Props.get("EmployeeName"));
+ assertEquals("2", employessNo2Props.get("RoomId"));
+ assertEquals(32, employessNo2Props.get("Age"));
+ @SuppressWarnings("unchecked")
+ Map<String, Object> emp2Location = (Map<String, Object>) employessNo2Props.get("Location");
+ @SuppressWarnings("unchecked")
+ Map<String, Object> emp2City = (Map<String, Object>) emp2Location.get("City");
+ assertEquals("69190", emp2City.get("PostalCode"));
+ assertEquals("Walldorf", emp2City.get("CityName"));
+ }
+
+ @Test
+ public void readWithInlineContentAndCallback_DEFAULT() throws Exception {
+ // prepare
+ String content = readFile("expanded_team.xml");
+ assertNotNull(content);
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+ InputStream reqContent = createContentAsStream(content);
+
+ // execute
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ DefaultCallback defaultCallback = new DefaultCallback();
+ EntityProviderReadProperties consumerProperties = EntityProviderReadProperties.init()
+ .mergeSemantic(false)
+ .callback(defaultCallback)
+ .build();
+
+ ODataEntry entry = xec.readEntry(entitySet, reqContent, consumerProperties);
+ // validate
+ assertNotNull(entry);
+ Map<String, Object> properties = entry.getProperties();
+ assertEquals("1", properties.get("Id"));
+ assertEquals("Team 1", properties.get("Name"));
+ assertEquals(Boolean.FALSE, properties.get("isScrumTeam"));
+ assertNull(properties.get("nt_Employees"));
+ //
+ ODataFeed employeesFeed = defaultCallback.asFeed("nt_Employees");
+ List<ODataEntry> employees = employeesFeed.getEntries();
+ assertEquals(3, employees.size());
+ //
+ ODataEntry employeeNo2 = employees.get(1);
+ Map<String, Object> employessNo2Props = employeeNo2.getProperties();
+ assertEquals("Frederic Fall", employessNo2Props.get("EmployeeName"));
+ assertEquals("2", employessNo2Props.get("RoomId"));
+ assertEquals(32, employessNo2Props.get("Age"));
+ @SuppressWarnings("unchecked")
+ Map<String, Object> emp2Location = (Map<String, Object>) employessNo2Props.get("Location");
+ @SuppressWarnings("unchecked")
+ Map<String, Object> emp2City = (Map<String, Object>) emp2Location.get("City");
+ assertEquals("69190", emp2City.get("PostalCode"));
+ assertEquals("Walldorf", emp2City.get("CityName"));
+ }
+
+ @Test
+ public void readInlineBuildingEntry() throws Exception {
+ // prepare
+ String content = readFile("expandedBuilding.xml");
+ assertNotNull(content);
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+ InputStream reqContent = createContentAsStream(content);
+
+ // execute
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ EntityProviderReadProperties consumerProperties = EntityProviderReadProperties.init()
+ .mergeSemantic(false).build();
+
+ ODataEntry entry = xec.readEntry(entitySet, reqContent, consumerProperties);
+ // validate
+ assertNotNull(entry);
+ Map<String, Object> properties = entry.getProperties();
+ assertEquals("1", properties.get("Id"));
+ assertEquals("Room 1", properties.get("Name"));
+ assertEquals((short) 1, properties.get("Seats"));
+ assertEquals((short) 1, properties.get("Version"));
+ //
+ ExpandSelectTreeNode expandTree = entry.getExpandSelectTree();
+ assertNotNull(expandTree);
+
+ ODataEntry inlineBuilding = (ODataEntry) properties.get("nr_Building");
+ Map<String, Object> inlineBuildingProps = inlineBuilding.getProperties();
+ assertEquals("1", inlineBuildingProps.get("Id"));
+ assertEquals("Building 1", inlineBuildingProps.get("Name"));
+ assertNull(inlineBuildingProps.get("Image"));
+ assertNull(inlineBuildingProps.get("nb_Rooms"));
+
+ assertEquals("Rooms('1')/nr_Employees", entry.getMetadata().getAssociationUris("nr_Employees").get(0));
+ assertEquals("Rooms('1')/nr_Building", entry.getMetadata().getAssociationUris("nr_Building").get(0));
+ }
+
+ /** Teams('1')?$expand=nt_Employees */
+ @Test
+ public void readWithInlineContent() throws Exception {
+ // prepare
+ String content = readFile("expanded_team.xml");
+ assertNotNull(content);
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+ InputStream reqContent = createContentAsStream(content);
+
+ // execute
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ EntityProviderReadProperties consumerProperties = EntityProviderReadProperties.init()
+ .mergeSemantic(false).build();
+
+ ODataEntry entry = xec.readEntry(entitySet, reqContent, consumerProperties);
+ // validate
+ assertNotNull(entry);
+ Map<String, Object> properties = entry.getProperties();
+ assertEquals("1", properties.get("Id"));
+ assertEquals("Team 1", properties.get("Name"));
+ assertEquals(Boolean.FALSE, properties.get("isScrumTeam"));
+ //
+ ExpandSelectTreeNode expandTree = entry.getExpandSelectTree();
+ assertNotNull(expandTree);
+ // TODO: do more testing here
+ //
+ ODataFeed employeesFeed = (ODataFeed) properties.get("nt_Employees");
+ List<ODataEntry> employees = employeesFeed.getEntries();
+ assertEquals(3, employees.size());
+ //
+ ODataEntry employeeNo2 = employees.get(1);
+ Map<String, Object> employessNo2Props = employeeNo2.getProperties();
+ assertEquals("Frederic Fall", employessNo2Props.get("EmployeeName"));
+ assertEquals("2", employessNo2Props.get("RoomId"));
+ assertEquals(32, employessNo2Props.get("Age"));
+ @SuppressWarnings("unchecked")
+ Map<String, Object> emp2Location = (Map<String, Object>) employessNo2Props.get("Location");
+ @SuppressWarnings("unchecked")
+ Map<String, Object> emp2City = (Map<String, Object>) emp2Location.get("City");
+ assertEquals("69190", emp2City.get("PostalCode"));
+ assertEquals("Walldorf", emp2City.get("CityName"));
+ }
+
+ /** Teams('1')?$expand=nt_Employees,nt_Employees/ne_Team */
+ @Test
+ public void readWithDoubleInlineContent() throws Exception {
+ // prepare
+ String content = readFile("double_expanded_team.xml");
+ assertNotNull(content);
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+ InputStream reqContent = createContentAsStream(content);
+
+ // execute
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ EntityProviderReadProperties consumerProperties = EntityProviderReadProperties.init().mergeSemantic(false).build();
+
+ ODataEntry entry = xec.readEntry(entitySet, reqContent, consumerProperties);
+ // validate
+ assertNotNull(entry);
+ Map<String, Object> properties = entry.getProperties();
+ assertEquals("1", properties.get("Id"));
+ assertEquals("Team 1", properties.get("Name"));
+ assertEquals(Boolean.FALSE, properties.get("isScrumTeam"));
+ //
+ ODataFeed employeesFeed = (ODataFeed) properties.get("nt_Employees");
+ List<ODataEntry> employees = employeesFeed.getEntries();
+ assertEquals(3, employees.size());
+ //
+ ODataEntry employeeNo2 = employees.get(1);
+ Map<String, Object> employessNo2Props = employeeNo2.getProperties();
+ assertEquals("Frederic Fall", employessNo2Props.get("EmployeeName"));
+ assertEquals("2", employessNo2Props.get("RoomId"));
+ assertEquals(32, employessNo2Props.get("Age"));
+ @SuppressWarnings("unchecked")
+ Map<String, Object> emp2Location = (Map<String, Object>) employessNo2Props.get("Location");
+ @SuppressWarnings("unchecked")
+ Map<String, Object> emp2City = (Map<String, Object>) emp2Location.get("City");
+ assertEquals("69190", emp2City.get("PostalCode"));
+ assertEquals("Walldorf", emp2City.get("CityName"));
+
+ ODataEntry inlinedTeam = (ODataEntry) employessNo2Props.get("ne_Team");
+ assertEquals("1", inlinedTeam.getProperties().get("Id"));
+ assertEquals("Team 1", inlinedTeam.getProperties().get("Name"));
+ }
+
+ /** Teams('1')?$expand=nt_Employees,nt_Employees/ne_Team */
+ @Test
+ @Ignore("Implementation doesn't support callback AND deep map")
+ public void readWithDoubleInlineContentAndResendCallback() throws Exception {
+ // prepare
+ String content = readFile("double_expanded_team.xml");
+ assertNotNull(content);
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+ InputStream reqContent = createContentAsStream(content);
+
+ // execute
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ DefaultCallback callbackHandler = new DefaultCallback();
+ EntityProviderReadProperties consumerProperties = EntityProviderReadProperties.init()
+ .mergeSemantic(false)
+ .callback(callbackHandler).build();
+
+ ODataEntry entry = xec.readEntry(entitySet, reqContent, consumerProperties);
+ // validate
+ assertNotNull(entry);
+ Map<String, Object> properties = entry.getProperties();
+ assertEquals("1", properties.get("Id"));
+ assertEquals("Team 1", properties.get("Name"));
+ assertEquals(Boolean.FALSE, properties.get("isScrumTeam"));
+ //
+ @SuppressWarnings("unchecked")
+ List<ODataEntry> employees = (List<ODataEntry>) properties.get("nt_Employees");
+ assertEquals(3, employees.size());
+ //
+ ODataEntry employeeNo2 = employees.get(1);
+ Map<String, Object> employessNo2Props = employeeNo2.getProperties();
+ assertEquals("Frederic Fall", employessNo2Props.get("EmployeeName"));
+ assertEquals("2", employessNo2Props.get("RoomId"));
+ assertEquals(32, employessNo2Props.get("Age"));
+ @SuppressWarnings("unchecked")
+ Map<String, Object> emp2Location = (Map<String, Object>) employessNo2Props.get("Location");
+ @SuppressWarnings("unchecked")
+ Map<String, Object> emp2City = (Map<String, Object>) emp2Location.get("City");
+ assertEquals("69190", emp2City.get("PostalCode"));
+ assertEquals("Walldorf", emp2City.get("CityName"));
+
+ ODataEntry inlinedTeam = (ODataEntry) employessNo2Props.get("ne_Team");
+ assertEquals("1", inlinedTeam.getProperties().get("Id"));
+ assertEquals("Team 1", inlinedTeam.getProperties().get("Name"));
+ }
+
+ /** Teams('1')?$expand=nt_Employees,nt_Employees/ne_Team */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void readWithDoubleInlineContentAndCallback() throws Exception {
+ // prepare
+ String content = readFile("double_expanded_team.xml");
+ assertNotNull(content);
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+ InputStream reqContent = createContentAsStream(content);
+
+ // execute
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ DefaultCallback callbackHandler = new DefaultCallback();
+ EntityProviderReadProperties consumerProperties = EntityProviderReadProperties.init()
+ .mergeSemantic(false)
+ .callback(callbackHandler)
+ .build();
+
+ ODataEntry entry = xec.readEntry(entitySet, reqContent, consumerProperties);
+ // validate
+ assertNotNull(entry);
+ Map<String, Object> properties = entry.getProperties();
+ assertEquals("1", properties.get("Id"));
+ assertEquals("Team 1", properties.get("Name"));
+ assertEquals(Boolean.FALSE, properties.get("isScrumTeam"));
+ // teams has no inlined content set
+ ODataFeed employeesFeed = (ODataFeed) properties.get("nt_Employees");
+ assertNull(employeesFeed);
+
+ // get inlined employees feed from callback
+ employeesFeed = callbackHandler.asFeed("nt_Employees");
+ List<ODataEntry> employees = employeesFeed.getEntries();
+ assertEquals(3, employees.size());
+ ODataEntry employeeNo2 = employees.get(1);
+ Map<String, Object> employessNo2Props = employeeNo2.getProperties();
+ assertEquals("Frederic Fall", employessNo2Props.get("EmployeeName"));
+ assertEquals("2", employessNo2Props.get("RoomId"));
+ assertEquals(32, employessNo2Props.get("Age"));
+ Map<String, Object> emp2Location = (Map<String, Object>) employessNo2Props.get("Location");
+ Map<String, Object> emp2City = (Map<String, Object>) emp2Location.get("City");
+ assertEquals("69190", emp2City.get("PostalCode"));
+ assertEquals("Walldorf", emp2City.get("CityName"));
+
+ // employees has no inlined content set
+ ODataEntry inlinedTeam = (ODataEntry) employessNo2Props.get("ne_Team");
+ assertNull(inlinedTeam);
+ // get inlined team from callback
+ inlinedTeam = callbackHandler.asEntry("ne_Team");
+ assertEquals("1", inlinedTeam.getProperties().get("Id"));
+ assertEquals("Team 1", inlinedTeam.getProperties().get("Name"));
+ }
+
+ @Test
+ public void readWithInlineContentIgnored() throws Exception {
+ // prepare
+ String content = readFile("expanded_team.xml");
+ assertNotNull(content);
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+ InputStream reqContent = createContentAsStream(content);
+
+ // execute
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ ODataEntry entry =
+ xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(false).build());
+
+ // validate
+ assertNotNull(entry);
+ Map<String, Object> properties = entry.getProperties();
+ assertEquals("1", properties.get("Id"));
+ assertEquals("Team 1", properties.get("Name"));
+ assertEquals(Boolean.FALSE, properties.get("isScrumTeam"));
+ }
+
+ /**
+ * Read an inline Room at an Employee
+ *
+ * @throws Exception
+ */
+ @Test
+ public void readWithInlineContentEmployeeRoomEntry() throws Exception {
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+ InputStream reqContent = createContentAsStream(EMPLOYEE_1_ROOM_XML);
+
+ // execute
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ ODataEntry entry =
+ xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(true).build());
+
+ // validate
+ assertNotNull(entry);
+ Map<String, Object> properties = entry.getProperties();
+ assertEquals("1", properties.get("EmployeeId"));
+ assertEquals("Walter Winter", properties.get("EmployeeName"));
+ ODataEntry room = (ODataEntry) properties.get("ne_Room");
+ Map<String, Object> roomProperties = room.getProperties();
+ assertEquals(4, roomProperties.size());
+ assertEquals("1", roomProperties.get("Id"));
+ assertEquals("Room 1", roomProperties.get("Name"));
+ assertEquals(Short.valueOf("1"), roomProperties.get("Seats"));
+ assertEquals(Short.valueOf("1"), roomProperties.get("Version"));
+ }
+
+ /**
+ * Reads an inline Room at an Employee with specially formatted XML (see issue ODATAFORSAP-92).
+ */
+ @Test
+ public void readWithInlineContentEmployeeRoomEntrySpecialXml() throws Exception {
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+ InputStream reqContent = createContentAsStream(EMPLOYEE_1_ROOM_XML, true);
+
+ // execute
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ ODataEntry entry =
+ xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(true).build());
+
+ // validate
+ assertNotNull(entry);
+ Map<String, Object> properties = entry.getProperties();
+ assertEquals("1", properties.get("EmployeeId"));
+ assertEquals("Walter Winter", properties.get("EmployeeName"));
+ ODataEntry room = (ODataEntry) properties.get("ne_Room");
+ Map<String, Object> roomProperties = room.getProperties();
+ assertEquals(4, roomProperties.size());
+ assertEquals("1", roomProperties.get("Id"));
+ assertEquals("Room 1", roomProperties.get("Name"));
+ assertEquals(Short.valueOf("1"), roomProperties.get("Seats"));
+ assertEquals(Short.valueOf("1"), roomProperties.get("Version"));
+ }
+
+ /**
+ * Reads an employee with inlined but <code>NULL</code> room navigation property
+ * (which has EdmMultiplicity#ONE).
+ */
+ @Test
+ public void readWithInlineContentEmployeeNullRoomEntry() throws Exception {
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+ InputStream reqContent = createContentAsStream(EMPLOYEE_1_NULL_ROOM_XML);
+
+ // execute
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ ODataEntry entry =
+ xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(true).build());
+
+ // validate
+ assertNotNull(entry);
+ Map<String, Object> properties = entry.getProperties();
+ assertEquals("1", properties.get("EmployeeId"));
+ assertEquals("Walter Winter", properties.get("EmployeeName"));
+ ODataEntry room = (ODataEntry) properties.get("ne_Room");
+ assertNull(room);
+ }
+
+ /**
+ * Reads an employee with inlined but <code>NULL</code> room navigation property
+ * (which has EdmMultiplicity#ONE).
+ */
+ @Test
+ public void readWithInlineContentEmployeeNullRoomEntrySpecialXmlFormat() throws Exception {
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+ InputStream reqContent = createContentAsStream(EMPLOYEE_1_NULL_ROOM_XML, true);
+
+ // execute
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ ODataEntry entry =
+ xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(true).build());
+
+ // validate
+ assertNotNull(entry);
+ Map<String, Object> properties = entry.getProperties();
+ assertEquals("1", properties.get("EmployeeId"));
+ assertEquals("Walter Winter", properties.get("EmployeeName"));
+ ODataEntry room = (ODataEntry) properties.get("ne_Room");
+ assertNull(room);
+ }
+
+ /**
+ * Reads a room with inlined but <code>NULL</code> employees navigation property
+ */
+ @Test
+ public void readWithInlineContentRoomNullEmployeesEntry() throws Exception {
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+ InputStream reqContent = createContentAsStream(ROOM_1_NULL_EMPLOYEE_XML);
+
+ // execute
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ ODataEntry entry =
+ xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(true).build());
+
+ // validate
+ assertNotNull(entry);
+ Map<String, Object> properties = entry.getProperties();
+ assertEquals("1", properties.get("Id"));
+ ODataEntry room = (ODataEntry) properties.get("ne_Employees");
+ assertNull(room);
+ }
+
+ /**
+ * Teams('1')?$expand=nt_Employees
+ * -> Remove 'feed' start and end tags around expanded/inlined employees
+ *
+ * @throws Exception
+ */
+ @Test(expected = EntityProviderException.class)
+ public void validateFeedForInlineContent() throws Exception {
+ // prepare
+ String content = readFile("expanded_team.xml")
+ .replace("<feed xml:base=\"http://some.host.com/service.root/\">", "")
+ .replace("</feed>", "");
+ assertNotNull(content);
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+ InputStream reqContent = createContentAsStream(content);
+
+ // execute
+ readAndExpectException(entitySet, reqContent,
+ EntityProviderException.INVALID_INLINE_CONTENT.addContent("xml data"));
+ }
+
+ /**
+ * Teams('1')?$expand=nt_Employees
+ * -> Remove 'type' attribute at expanded/inlined employees link tag
+ *
+ * @throws Exception
+ */
+ @Test(expected = EntityProviderException.class)
+ public void validateMissingTypeAttributeForInlineContent() throws Exception {
+ // prepare
+ String content = readFile("expanded_team.xml")
+ .replace("type=\"application/atom+xml;type=feed\"", "");
+ assertNotNull(content);
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+ InputStream reqContent = createContentAsStream(content);
+
+ // execute
+ readAndExpectException(entitySet, reqContent,
+ EntityProviderException.INVALID_INLINE_CONTENT.addContent("xml data"));
+ }
+
+ /**
+ * Teams('1')?$expand=nt_Employees
+ * -> Replaced parameter 'type=feed' with 'type=entry' attribute at expanded/inlined employees link tag
+ *
+ * @throws Exception
+ */
+ @Test(expected = EntityProviderException.class)
+ public void validateWrongTypeAttributeForInlineContent() throws Exception {
+ // prepare
+ String content = readFile("expanded_team.xml")
+ .replace("type=\"application/atom+xml;type=feed\"", "type=\"application/atom+xml;type=entry\"");
+ assertNotNull(content);
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+ InputStream reqContent = createContentAsStream(content);
+
+ // execute
+ readAndExpectException(entitySet, reqContent, EntityProviderException.INVALID_INLINE_CONTENT.addContent("feed"));
+ }
+
+ /**
+ * Teams('1')?$expand=nt_Employees
+ * -> Replaced parameter 'type=feed' with 'type=entry' attribute at expanded/inlined employees link tag
+ *
+ * @throws Exception
+ */
+ @Test(expected = EntityProviderException.class)
+ public void validateWrongTypeAttributeForInlineContentMany() throws Exception {
+ // prepare
+ String content = readFile("double_expanded_team.xml")
+ .replace("type=\"application/atom+xml;type=entry\"", "type=\"application/atom+xml;type=feed\"");
+ assertNotNull(content);
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+ InputStream reqContent = createContentAsStream(content);
+
+ // execute
+ readAndExpectException(entitySet, reqContent, EntityProviderException.INVALID_INLINE_CONTENT.addContent("entry"));
+ }
+
+ /**
+ * We only support <code>UTF-8</code> as character encoding.
+ *
+ * @throws Exception
+ */
+ @Test(expected = EntityProviderException.class)
+ public void validationOfWrongXmlEncodingUtf32() throws Exception {
+ String roomWithValidNamespaces =
+ "<?xml version='1.0' encoding='UTF-32'?>"
+ +
+ "<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/test/\" m:etag=\"W/"1"\">"
+ +
+ "</entry>";
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+ InputStream reqContent = createContentAsStream(roomWithValidNamespaces);
+ readAndExpectException(entitySet, reqContent, EntityProviderException.UNSUPPORTED_CHARACTER_ENCODING
+ .addContent("UTF-32"));
+ }
+
+ /**
+ * We only support <code>UTF-8</code> as character encoding.
+ *
+ * @throws Exception
+ */
+ @Test(expected = EntityProviderException.class)
+ public void validationOfWrongXmlEncodingIso8859_1() throws Exception {
+ String roomWithValidNamespaces =
+ "<?xml version='1.0' encoding='iso-8859-1'?>"
+ +
+ "<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/test/\" m:etag=\"W/"1"\">"
+ +
+ "</entry>";
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+ InputStream reqContent = createContentAsStream(roomWithValidNamespaces);
+ readAndExpectException(entitySet, reqContent, EntityProviderException.UNSUPPORTED_CHARACTER_ENCODING
+ .addContent("iso-8859-1"));
+ }
+
+ /**
+ * Character encodings are case insensitive.
+ * Hence <code>uTf-8</code> should work as well as <code>UTF-8</code>.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void validationCaseInsensitiveXmlEncodingUtf8() throws Exception {
+ String room =
+ "<?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/test/\" m:etag=\"W/"1"\">"
+ +
+ " <id>http://localhost:19000/test/Rooms('1')</id>" +
+ " <title type=\"text\">Room 1</title>" +
+ " <updated>2013-01-11T13:50:50.541+01:00</updated>" +
+ " <content type=\"application/xml\">" +
+ " <m:properties>" +
+ " <d:Id>1</d:Id>" +
+ " </m:properties>" +
+ " </content>" +
+ "</entry>";
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+ InputStream reqContent = createContentAsStream(room);
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ ODataEntry result =
+ xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(true).build());
+
+ assertNotNull(result);
+ assertEquals("1", result.getProperties().get("Id"));
+ }
+
+ /**
+ * For none media resource if <code>properties</code> tag is not within <code>content</code> tag it results in an
+ * exception.
+ *
+ * OData specification v2: 2.2.6.2.2 Entity Type (as an Atom Entry Element)
+ *
+ * @throws Exception
+ */
+ @Test(expected = EntityProviderException.class)
+ public void validationOfWrongPropertiesTagPositionForNoneMediaLinkEntry() throws Exception {
+ String roomWithValidNamespaces =
+ "<?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/test/\" m:etag=\"W/"1"\">"
+ +
+ " <id>http://localhost:19000/test/Rooms('1')</id>" +
+ " <title type=\"text\">Room 1</title>" +
+ " <updated>2013-01-11T13:50:50.541+01:00</updated>" +
+ " <content type=\"application/xml\" />" +
+ " <m:properties>" +
+ " <d:Id>1</d:Id>" +
+ " </m:properties>" +
+ "</entry>";
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+ InputStream reqContent = createContentAsStream(roomWithValidNamespaces);
+ readAndExpectException(entitySet, reqContent, EntityProviderException.INVALID_PARENT_TAG.addContent("content")
+ .addContent("properties"));
+ }
+
+ /**
+ * For media resource if <code>properties</code> tag is within <code>content</code> tag it results in an exception.
+ *
+ * OData specification v2: 2.2.6.2.2 Entity Type (as an Atom Entry Element)
+ * And RFC5023 [section 4.2]
+ *
+ * @throws Exception
+ */
+ @Test(expected = EntityProviderException.class)
+ public void validationOfWrongPropertiesTagPositionForMediaLinkEntry() throws Exception {
+ String roomWithValidNamespaces =
+ "<?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/test/\" m:etag=\"W/"1"\">"
+ +
+ " <id>http://localhost:19000/test/Employees('1')</id>" +
+ " <title type=\"text\">Walter Winter</title>" +
+ " <updated>2013-01-11T13:50:50.541+01:00</updated>" +
+ " <content type=\"application/xml\">" +
+ " <m:properties>" +
+ " <d:EmployeeId>1</d:EmployeeId>" +
+ " </m:properties>" +
+ " </content>" +
+ "</entry>";
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+ InputStream reqContent = createContentAsStream(roomWithValidNamespaces);
+ readAndExpectException(entitySet, reqContent, EntityProviderException.INVALID_PARENT_TAG.addContent("properties")
+ .addContent("content"));
+ }
+
+ @Test
+ public void validationOfNamespacesSuccess() throws Exception {
+ String roomWithValidNamespaces =
+ "<?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/test/\" m:etag=\"W/"1"\">"
+ +
+ " <id>http://localhost:19000/test/Rooms('1')</id>" +
+ " <title type=\"text\">Room 1</title>" +
+ " <updated>2013-01-11T13:50:50.541+01:00</updated>" +
+ " <content type=\"application/xml\">" +
+ " <m:properties>" +
+ " <d:Id>1</d:Id>" +
+ " </m:properties>" +
+ " </content>" +
+ "</entry>";
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+ InputStream reqContent = createContentAsStream(roomWithValidNamespaces);
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ ODataEntry result =
+ xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(true).build());
+ assertNotNull(result);
+ }
+
+ @Test
+ public void validationOfNamespaceAtPropertiesSuccess() throws Exception {
+ String roomWithValidNamespaces =
+ "<?xml version='1.0' encoding='UTF-8'?>" +
+ "<entry xmlns=\"http://www.w3.org/2005/Atom\" xml:base=\"http://localhost:19000/test/\">" +
+ " <id>http://localhost:19000/test/Rooms('1')</id>" +
+ " <title type=\"text\">Room 1</title>" +
+ " <updated>2013-01-11T13:50:50.541+01:00</updated>" +
+ " <content type=\"application/xml\">" +
+ " <m:properties xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\">" +
+ " <d:Id xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices\">1</d:Id>" +
+ " </m:properties>" +
+ " </content>" +
+ "</entry>";
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+ InputStream reqContent = createContentAsStream(roomWithValidNamespaces);
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ ODataEntry result =
+ xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(true).build());
+ assertNotNull(result);
+ }
+
+ @Test(expected = EntityProviderException.class)
+ public void validationOfNamespaceAtTagsMissing() throws Exception {
+ String roomWithValidNamespaces =
+ "<?xml version='1.0' encoding='UTF-8'?>" +
+ "<entry xmlns=\"http://www.w3.org/2005/Atom\" xml:base=\"http://localhost:19000/test/\">" +
+ " <id>http://localhost:19000/test/Rooms('1')</id>" +
+ " <title type=\"text\">Room 1</title>" +
+ " <updated>2013-01-11T13:50:50.541+01:00</updated>" +
+ " <content type=\"application/xml\">" +
+ " <m:properties>" +
+ " <d:Id>1</d:Id>" +
+ " </m:properties>" +
+ " </content>" +
+ "</entry>";
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+ InputStream reqContent = createContentAsStream(roomWithValidNamespaces);
+ readAndExpectException(entitySet, reqContent, EntityProviderException.EXCEPTION_OCCURRED
+ .addContent("WstxParsingException"));
+ }
+
+ /**
+ * Use different namespace prefixes for <code>metadata (m)</code> and <code>data (d)</code>.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void validationOfDifferentNamespacesPrefixSuccess() throws Exception {
+ String roomWithValidNamespaces =
+ "<?xml version='1.0' encoding='UTF-8'?>" +
+ "<entry xmlns=\"http://www.w3.org/2005/Atom\" " +
+ " xmlns:meta=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\" " +
+ " xmlns:data=\"http://schemas.microsoft.com/ado/2007/08/dataservices\" " +
+ " xml:base=\"http://localhost:19000/test/\" " +
+ " meta:etag=\"W/"1"\">" +
+ "" +
+ " <id>http://localhost:19000/test/Rooms('1')</id>" +
+ " <title type=\"text\">Room 1</title>" +
+ " <updated>2013-01-11T13:50:50.541+01:00</updated>" +
+ " <content type=\"application/xml\">" +
+ " <meta:properties>" +
+ " <data:Id>1</data:Id>" +
+ " <data:Seats>11</data:Seats>" +
+ " <data:Name>Room 42</data:Name>" +
+ " <data:Version>4711</data:Version>" +
+ " </meta:properties>" +
+ " </content>" +
+ "</entry>";
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+ InputStream reqContent = createContentAsStream(roomWithValidNamespaces);
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ ODataEntry result =
+ xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(false).build());
+ assertNotNull(result);
+ }
+
+ /**
+ * Add <code>unknown property</code> in own namespace which is defined in entry tag.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void validationOfUnknownPropertyOwnNamespaceSuccess() throws Exception {
+ String roomWithValidNamespaces =
+ "<?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\" " +
+ " xmlns:more=\"http://sample.com/more\" " +
+ " xml:base=\"http://localhost:19000/test/\" " +
+ " m:etag=\"W/"1"\">" +
+ "" +
+ " <id>http://localhost:19000/test/Rooms('1')</id>" +
+ " <title type=\"text\">Room 1</title>" +
+ " <updated>2013-01-11T13:50:50.541+01:00</updated>" +
+ " <content type=\"application/xml\">" +
+ " <m:properties>" +
+ " <d:Id>1</d:Id>" +
+ " <more:somePropertyToBeIgnored>ignore me</more:somePropertyToBeIgnored>" +
+ " <d:Seats>11</d:Seats>" +
+ " <d:Name>Room 42</d:Name>" +
+ " <d:Version>4711</d:Version>" +
+ " </m:properties>" +
+ " </content>" +
+ "</entry>";
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+ InputStream reqContent = createContentAsStream(roomWithValidNamespaces);
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ ODataEntry result =
+ xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(false).build());
+ assertNotNull(result);
+ }
+
+ /**
+ * Is allowed because <code>Id</code> is in default namespace (<code>xmlns=\"http://www.w3.org/2005/Atom\"</code>)
+ *
+ * @throws Exception
+ */
+ @Test
+ public void validationOfUnknownPropertyDefaultNamespaceSuccess() throws Exception {
+ String roomWithValidNamespaces =
+ "<?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/test/\" m:etag=\"W/"1"\">"
+ +
+ " <id>http://localhost:19000/test/Rooms('1')</id>" +
+ " <title type=\"text\">Room 1</title>" +
+ " <updated>2013-01-11T13:50:50.541+01:00</updated>" +
+ " <content type=\"application/xml\">" +
+ " <m:properties>" +
+ " <Id>1</Id>" +
+ " </m:properties>" +
+ " </content>" +
+ "</entry>";
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+ InputStream reqContent = createContentAsStream(roomWithValidNamespaces);
+
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ ODataEntry result =
+ xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(true).build());
+ assertNotNull(result);
+ }
+
+ /**
+ * Add <code>unknown property</code> in own namespace which is defined directly in unknown tag.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void validationOfUnknownPropertyInlineNamespaceSuccess() throws Exception {
+ String roomWithValidNamespaces =
+ "<?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/test/\" "
+ +
+ " m:etag=\"W/"1"\">"
+ +
+ ""
+ +
+ " <id>http://localhost:19000/test/Rooms('1')</id>"
+ +
+ " <title type=\"text\">Room 1</title>"
+ +
+ " <updated>2013-01-11T13:50:50.541+01:00</updated>"
+ +
+ " <content type=\"application/xml\">"
+ +
+ " <m:properties>"
+ +
+ " <d:Id>1</d:Id>"
+ +
+ " <more:somePropertyToBeIgnored " +
+ "xmlns:more=\"http://sample.com/more\">ignore me</more:somePropertyToBeIgnored>"
+ +
+ " <d:Seats>11</d:Seats>" +
+ " <d:Name>Room 42</d:Name>" +
+ " <d:Version>4711</d:Version>" +
+ " </m:properties>" +
+ " </content>" +
+ "</entry>";
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+ InputStream reqContent = createContentAsStream(roomWithValidNamespaces);
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ ODataEntry result =
+ xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(false).build());
+ assertNotNull(result);
+ }
+
+ @Test(expected = EntityProviderException.class)
+ public void validationOfNamespacesMissingXmlns() throws Exception {
+ String roomWithValidNamespaces =
+ "<?xml version='1.0' encoding='UTF-8'?>" +
+ "<entry etag=\"W/"1"\">" +
+ " <id>http://localhost:19000/test/Rooms('1')</id>" +
+ " <content type=\"application/xml\">" +
+ " <m:properties>" +
+ " <d:Id>1</d:Id>" +
+ " </m:properties>" +
+ " </content>" +
+ "</entry>";
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+ InputStream reqContent = createContentAsStream(roomWithValidNamespaces);
+ readAndExpectException(entitySet, reqContent, EntityProviderException.EXCEPTION_OCCURRED
+ .addContent("WstxParsingException"));
+ }
+
+ /**
+ * Double occurrence of <code>d:Name</code> tag must result in an exception.
+ *
+ * @throws Exception
+ */
+ @Test(expected = EntityProviderException.class)
+ public void validationOfDuplicatedPropertyException() throws Exception {
+ String room =
+ "<?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/test/\" " +
+ " m:etag=\"W/"1"\">" +
+ "" +
+ " <id>http://localhost:19000/test/Rooms('1')</id>" +
+ " <title type=\"text\">Room 1</title>" +
+ " <updated>2013-01-11T13:50:50.541+01:00</updated>" +
+ " <content type=\"application/xml\">" +
+ " <m:properties>" +
+ " <d:Id>1</d:Id>" +
+ " <d:Seats>11</d:Seats>" +
+ " <d:Name>Room 42</d:Name>" +
+ " <d:Name>Room 42</d:Name>" +
+ " <d:Version>4711</d:Version>" +
+ " </m:properties>" +
+ " </content>" +
+ "</entry>";
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+ InputStream reqContent = createContentAsStream(room);
+ readAndExpectException(entitySet, reqContent, EntityProviderException.DOUBLE_PROPERTY.addContent("Name"));
+ }
+
+ /**
+ * Double occurrence of <code>Name</code> tag within different namespace is allowed.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void validationOfDoublePropertyDifferentNamespace() throws Exception {
+ String room =
+ "<?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/test/\" " +
+ " m:etag=\"W/"1"\">" +
+ "" +
+ " <id>http://localhost:19000/test/Rooms('1')</id>" +
+ " <title type=\"text\">Room 1</title>" +
+ " <updated>2013-01-11T13:50:50.541+01:00</updated>" +
+ " <content type=\"application/xml\">" +
+ " <m:properties>" +
+ " <d:Id>1</d:Id>" +
+ " <d:Seats>11</d:Seats>" +
+ " <o:Name xmlns:o=\"http://sample.org/own\">Room 42</o:Name>" +
+ " <d:Name>Room 42</d:Name>" +
+ " <d:Version>4711</d:Version>" +
+ " </m:properties>" +
+ " </content>" +
+ "</entry>";
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+ InputStream reqContent = createContentAsStream(room);
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ ODataEntry result =
+ xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(false).build());
+ assertNotNull(result);
+ }
+
+ /**
+ * Double occurrence of <code>Name</code> tag within ignored/unknown property AND different namespace is allowed.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void validationOfDoublePropertyDifferentTagHierachy() throws Exception {
+ String room =
+ "<?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/test/\" " +
+ " m:etag=\"W/"1"\">" +
+ "" +
+ " <id>http://localhost:19000/test/Rooms('1')</id>" +
+ " <title type=\"text\">Room 1</title>" +
+ " <updated>2013-01-11T13:50:50.541+01:00</updated>" +
+ " <content type=\"application/xml\">" +
+ " <m:properties>" +
+ " <d:Id>1</d:Id>" +
+ " <d:Seats>11</d:Seats>" +
+ " <SomeProp>" +
+ " <Name>Room 42</Name>" +
+ " </SomeProp>" +
+ " <d:Name>Room 42</d:Name>" +
+ " <d:Version>4711</d:Version>" +
+ " </m:properties>" +
+ " </content>" +
+ "</entry>";
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+ InputStream reqContent = createContentAsStream(room);
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ ODataEntry result =
+ xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(false).build());
+ assertNotNull(result);
+ }
+
+ /**
+ * Double occurrence of <code>d:Name</code> tag within an unknown (and hence ignored) property is allowed.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void validationOfDoublePropertyDifferentTagHierachyD_Namespace() throws Exception {
+ String room =
+ "<?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/test/\" " +
+ " m:etag=\"W/"1"\">" +
+ "" +
+ " <id>http://localhost:19000/test/Rooms('1')</id>" +
+ " <title type=\"text\">Room 1</title>" +
+ " <updated>2013-01-11T13:50:50.541+01:00</updated>" +
+ " <content type=\"application/xml\">" +
+ " <m:properties>" +
+ " <d:Id>1</d:Id>" +
+ " <d:Seats>11</d:Seats>" +
+ " <SomeProp>" +
+ " <d:Name>Room 42</d:Name>" +
+ " </SomeProp>" +
+ " <d:Name>Room 42</d:Name>" +
+ " <d:Version>4711</d:Version>" +
+ " </m:properties>" +
+ " </content>" +
+ "</entry>";
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+ InputStream reqContent = createContentAsStream(room);
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ ODataEntry result =
+ xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(false).build());
+ assertNotNull(result);
+ }
+
+ @Test(expected = EntityProviderException.class)
+ public void validationOfNamespacesMissingM_NamespaceAtProperties() throws Exception {
+ String roomWithValidNamespaces =
+ "<?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/test/\" m:etag=\"W/"1"\">"
+ +
+ " <id>http://localhost:19000/test/Rooms('1')</id>" +
+ " <title type=\"text\">Room 1</title>" +
+ " <updated>2013-01-11T13:50:50.541+01:00</updated>" +
+ " <content type=\"application/xml\">" +
+ " <properties>" +
+ " <d:Id>1</d:Id>" +
+ " </properties>" +
+ " </content>" +
+ "</entry>";
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+ InputStream reqContent = createContentAsStream(roomWithValidNamespaces);
+ readAndExpectException(entitySet, reqContent, EntityProviderException.EXCEPTION_OCCURRED
+ .addContent("WstxParsingException"));
+ }
+
+ /**
+ * Missing _d_ namespace at key property/tag (_id_) is allowed.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void validationOfNamespacesMissingD_NamespaceAtKeyPropertyTag() throws Exception {
+ String roomWithValidNamespaces =
+ "<?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/test/\" m:etag=\"W/"1"\">"
+ +
+ " <id>http://localhost:19000/test/Rooms('1')</id>" +
+ " <title type=\"text\">Room 1</title>" +
+ " <updated>2013-01-11T13:50:50.541+01:00</updated>" +
+ " <content type=\"application/xml\">" +
+ " <m:properties>" +
+ " <Id>1</Id>" +
+ " <d:Seats>11</d:Seats>" +
+ " <d:Name>Room 42</d:Name>" +
+ " <d:Version>4711</d:Version>" +
+ " </m:properties>" +
+ " </content>" +
+ "</entry>";
+
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+ InputStream reqContent = createContentAsStream(roomWithValidNamespaces);
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ ODataEntry result =
+ xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(false).build());
+ assertNotNull(result);
+ }
+
+ /**
+ * Missing _d_ namespace at non-nullable property/tag (_Version_) is allowed.
+ * @throws Exception
+ */
+ public void validationOfNamespacesMissingD_NamespaceAtNonNullableTag() throws Exception {
+ String roomWithValidNamespaces =
+ "<?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/test/\" m:etag=\"W/"1"\">"
+ +
+ " <id>http://localhost:19000/test/Rooms('1')</id>" +
+ " <title type=\"text\">Room 1</title>" +
+ " <updated>2013-01-11T13:50:50.541+01:00</updated>" +
+ " <content type=\"application/xml\">" +
+ " <m:properties>" +
+ " <d:Seats>11</d:Seats>" +
+ " <d:Name>Room 42</d:Name>" +
+ " <Version>4711</Version>" +
+ " </m:properties>" +
+ " </content>" +
+ "</entry>";
+
+ final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+ final EdmProperty property = (EdmProperty) entitySet.getEntityType().getProperty("Version");
+ EdmFacets facets = property.getFacets();
+ Mockito.when(facets.isNullable()).thenReturn(false);
+
+ InputStream reqContent = createContentAsStream(roomWithValidNamespaces);
+ final ODataEntry result =
+ new XmlEntityConsumer().readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(
+ false).build());
+ assertNotNull(result);
+ }
+
+ private void readAndExpectException(final EdmEntitySet entitySet, final InputStream reqContent,
+ final MessageReference messageReference) throws ODataMessageException {
+ readAndExpectException(entitySet, reqContent, true, messageReference);
+ }
+
+ private void readAndExpectException(final EdmEntitySet entitySet, final InputStream reqContent, final boolean merge,
+ final MessageReference messageReference) throws ODataMessageException {
+ try {
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ ODataEntry result =
+ xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(merge).build());
+ assertNotNull(result);
+ Assert.fail("Expected exception with MessageReference '" + messageReference.getKey() + "' was not thrown.");
+ } catch (ODataMessageException e) {
+ assertEquals(messageReference.getKey(), e.getMessageReference().getKey());
+ // assertEquals(messageReference.getContent(), e.getMessageReference().getContent());
+ throw e;
+ }
+ }
+
+ @Test
+ public void readEntryAtomProperties() throws Exception {
+ // prepare
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+ InputStream contentBody = createContentAsStream(EMPLOYEE_1_XML);
+
+ // execute
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ ODataEntry result =
+ xec.readEntry(entitySet, contentBody, EntityProviderReadProperties.init().mergeSemantic(true).build());
+
+ // verify
+ EntryMetadata metadata = result.getMetadata();
+ assertEquals("http://localhost:19000/Employees('1')", metadata.getId());
+ assertEquals("W/\"1\"", metadata.getEtag());
+ List<String> associationUris = metadata.getAssociationUris("ne_Room");
+ assertEquals(1, associationUris.size());
+ assertEquals("Employees('1')/ne_Room", associationUris.get(0));
+ associationUris = metadata.getAssociationUris("ne_Manager");
+ assertEquals(1, associationUris.size());
+ assertEquals("Employees('1')/ne_Manager", associationUris.get(0));
+ associationUris = metadata.getAssociationUris("ne_Team");
+ assertEquals(1, associationUris.size());
+ assertEquals("Employees('1')/ne_Team", associationUris.get(0));
+
+ assertEquals(null, metadata.getUri());
+
+ MediaMetadata mm = result.getMediaMetadata();
+ assertEquals("Employees('1')/$value", mm.getSourceLink());
+ assertEquals("mmEtag", mm.getEtag());
+ assertEquals("application/octet-stream", mm.getContentType());
+ assertEquals("Employees('1')/$value", mm.getEditLink());
+
+ Map<String, Object> data = result.getProperties();
+ assertEquals(9, data.size());
+ assertEquals("1", data.get("EmployeeId"));
+ assertEquals("Walter Winter", data.get("EmployeeName"));
+ assertEquals("1", data.get("ManagerId"));
+ assertEquals("1", data.get("RoomId"));
+ assertEquals("1", data.get("TeamId"));
+ }
+
+ @Test
+ public void readEntryLinks() throws Exception {
+ // prepare
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+ InputStream contentBody = createContentAsStream(EMPLOYEE_1_XML);
+
+ // execute
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ ODataEntry result =
+ xec.readEntry(entitySet, contentBody, EntityProviderReadProperties.init().mergeSemantic(true).build());
+
+ // verify
+ List<String> associationUris = result.getMetadata().getAssociationUris("ne_Room");
+ assertEquals(1, associationUris.size());
+ assertEquals("Employees('1')/ne_Room", associationUris.get(0));
+ associationUris = result.getMetadata().getAssociationUris("ne_Manager");
+ assertEquals(1, associationUris.size());
+ assertEquals("Employees('1')/ne_Manager", associationUris.get(0));
+ associationUris = result.getMetadata().getAssociationUris("ne_Team");
+ assertEquals(1, associationUris.size());
+ assertEquals("Employees('1')/ne_Team", associationUris.get(0));
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testReadFeed() throws Exception {
+ // prepare
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+ String content = readFile("feed_employees.xml");
+ InputStream contentAsStream = createContentAsStream(content);
+
+ // execute
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ ODataFeed feedResult =
+ xec.readFeed(entitySet, contentAsStream, EntityProviderReadProperties.init().mergeSemantic(false).build());
+
+ // verify feed result
+ // metadata
+ FeedMetadata metadata = feedResult.getFeedMetadata();
+ assertNull(metadata.getInlineCount());
+ assertNull(metadata.getNextLink());
+ assertNull(metadata.getDeltaLink());
+ // entries
+ List<ODataEntry> entries = feedResult.getEntries();
+ assertEquals(6, entries.size());
+ // verify first employee
+ ODataEntry firstEmployee = entries.get(0);
+ Map<String, Object> properties = firstEmployee.getProperties();
+ assertEquals(9, properties.size());
+
+ assertEquals("1", properties.get("EmployeeId"));
+ assertEquals("Walter Winter", properties.get("EmployeeName"));
+ assertEquals("1", properties.get("ManagerId"));
+ assertEquals("1", properties.get("RoomId"));
+ assertEquals("1", properties.get("TeamId"));
+ Map<String, Object> location = (Map<String, Object>) properties.get("Location");
+ assertEquals(2, location.size());
+ assertEquals("Germany", location.get("Country"));
+ Map<String, Object> city = (Map<String, Object>) location.get("City");
+ assertEquals(2, city.size());
+ assertEquals("69124", city.get("PostalCode"));
+ assertEquals("Heidelberg", city.get("CityName"));
+ assertEquals(Integer.valueOf(52), properties.get("Age"));
+ Calendar entryDate = (Calendar) properties.get("EntryDate");
+ assertEquals(915148800000L, entryDate.getTimeInMillis());
+ assertEquals(TimeZone.getTimeZone("GMT"), entryDate.getTimeZone());
+ assertEquals("Employees('1')/$value", properties.get("ImageUrl"));
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testReadFeedWithInlineCountAndNextLink() throws Exception {
+ // prepare
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+ String content = readFile("feed_employees_full.xml");
+ InputStream contentAsStream = createContentAsStream(content);
+
+ // execute
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ ODataFeed feedResult =
+ xec.readFeed(entitySet, contentAsStream, EntityProviderReadProperties.init().mergeSemantic(false).build());
+
+ // verify feed result
+ // metadata
+ FeedMetadata metadata = feedResult.getFeedMetadata();
+ assertEquals(Integer.valueOf(6), metadata.getInlineCount());
+ assertEquals("http://thisisanextlink", metadata.getNextLink());
+ assertNull(metadata.getDeltaLink());
+ // entries
+ List<ODataEntry> entries = feedResult.getEntries();
+ assertEquals(6, entries.size());
+ // verify first employee
+ ODataEntry firstEmployee = entries.get(0);
+ Map<String, Object> properties = firstEmployee.getProperties();
+ assertEquals(9, properties.size());
+
+ assertEquals("1", properties.get("EmployeeId"));
+ assertEquals("Walter Winter", properties.get("EmployeeName"));
+ assertEquals("1", properties.get("ManagerId"));
+ assertEquals("1", properties.get("RoomId"));
+ assertEquals("1", properties.get("TeamId"));
+ Map<String, Object> location = (Map<String, Object>) properties.get("Location");
+ assertEquals(2, location.size());
+ assertEquals("Germany", location.get("Country"));
+ Map<String, Object> city = (Map<String, Object>) location.get("City");
+ assertEquals(2, city.size());
+ assertEquals("69124", city.get("PostalCode"));
+ assertEquals("Heidelberg", city.get("CityName"));
+ assertEquals(Integer.valueOf(52), properties.get("Age"));
+ Calendar entryDate = (Calendar) properties.get("EntryDate");
+ assertEquals(915148800000L, entryDate.getTimeInMillis());
+ assertEquals(TimeZone.getTimeZone("GMT"), entryDate.getTimeZone());
+ assertEquals("Employees('1')/$value", properties.get("ImageUrl"));
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testReadEntry() throws Exception {
+ // prepare
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+ InputStream contentBody = createContentAsStream(EMPLOYEE_1_XML);
+
+ // execute
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ ODataEntry result =
+ xec.readEntry(entitySet, contentBody, EntityProviderReadProperties.init().mergeSemantic(false).build());
+
+ // verify
+ Map<String, Object> properties = result.getProperties();
+ assertEquals(9, properties.size());
+
+ assertEquals("1", properties.get("EmployeeId"));
+ assertEquals("Walter Winter", properties.get("EmployeeName"));
+ assertEquals("1", properties.get("ManagerId"));
+ assertEquals("1", properties.get("RoomId"));
+ assertEquals("1", properties.get("TeamId"));
+ Map<String, Object> location = (Map<String, Object>) properties.get("Location");
+ assertEquals(2, location.size());
+ assertEquals("Germany", location.get("Country"));
+ Map<String, Object> city = (Map<String, Object>) location.get("City");
+ assertEquals(2, city.size());
+ assertEquals("69124", city.get("PostalCode"));
+ assertEquals("Heidelberg", city.get("CityName"));
+ assertEquals(Integer.valueOf(52), properties.get("Age"));
+ Calendar entryDate = (Calendar) properties.get("EntryDate");
+ assertEquals(915148800000L, entryDate.getTimeInMillis());
+ assertEquals(TimeZone.getTimeZone("GMT"), entryDate.getTimeZone());
+ assertEquals("/SAP/PUBLIC/BC/NWDEMO_MODEL/IMAGES/Employee_1.png", properties.get("ImageUrl"));
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testReadEntryWithLargeProperty() throws Exception {
+ // prepare
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+ String newName = StringHelper.generateData(81920);
+ InputStream contentBody = createContentAsStream(EMPLOYEE_1_XML.replaceAll("Walter Winter", newName));
+
+ // execute
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ ODataEntry result =
+ xec.readEntry(entitySet, contentBody, EntityProviderReadProperties.init().mergeSemantic(false).build());
+
+ // verify
+ Map<String, Object> properties = result.getProperties();
+ assertEquals(9, properties.size());
+
+ assertEquals("1", properties.get("EmployeeId"));
+ assertEquals(newName, properties.get("EmployeeName"));
+ assertEquals("1", properties.get("ManagerId"));
+ assertEquals("1", properties.get("RoomId"));
+ assertEquals("1", properties.get("TeamId"));
+ Map<String, Object> location = (Map<String, Object>) properties.get("Location");
+ assertEquals(2, location.size());
+ assertEquals("Germany", location.get("Country"));
+ Map<String, Object> city = (Map<String, Object>) location.get("City");
+ assertEquals(2, city.size());
+ assertEquals("69124", city.get("PostalCode"));
+ assertEquals("Heidelberg", city.get("CityName"));
+ assertEquals(Integer.valueOf(52), properties.get("Age"));
+ Calendar entryDate = (Calendar) properties.get("EntryDate");
+ assertEquals(915148800000L, entryDate.getTimeInMillis());
+ assertEquals(TimeZone.getTimeZone("GMT"), entryDate.getTimeZone());
+ assertEquals("/SAP/PUBLIC/BC/NWDEMO_MODEL/IMAGES/Employee_1.png", properties.get("ImageUrl"));
+ }
+
+ /**
+ * Missing 'key' properties are allowed for validation against Edm model.
+ * @throws Exception
+ */
+ @Test
+ @SuppressWarnings("unchecked")
+ public void testReadEntryMissingKeyProperty() throws Exception {
+ // prepare
+ final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+ InputStream contentBody = createContentAsStream(EMPLOYEE_1_XML.replace("<d:EmployeeId>1</d:EmployeeId>", ""));
+
+ // execute
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ ODataEntry result =
+ xec.readEntry(entitySet, contentBody, EntityProviderReadProperties.init().mergeSemantic(false).build());
+
+ // verify
+ Map<String, Object> properties = result.getProperties();
+ assertEquals(8, properties.size());
+
+ assertNull(properties.get("EmployeeId"));
+ assertEquals("Walter Winter", properties.get("EmployeeName"));
+ assertEquals("1", properties.get("ManagerId"));
+ assertEquals("1", properties.get("RoomId"));
+ assertEquals("1", properties.get("TeamId"));
+ Map<String, Object> location = (Map<String, Object>) properties.get("Location");
+ assertEquals(2, location.size());
+ assertEquals("Germany", location.get("Country"));
+ Map<String, Object> city = (Map<String, Object>) location.get("City");
+ assertEquals(2, city.size());
+ assertEquals("69124", city.get("PostalCode"));
+ assertEquals("Heidelberg", city.get("CityName"));
+ assertEquals(Integer.valueOf(52), properties.get("Age"));
+ Calendar entryDate = (Calendar) properties.get("EntryDate");
+ assertEquals(915148800000L, entryDate.getTimeInMillis());
+ assertEquals(TimeZone.getTimeZone("GMT"), entryDate.getTimeZone());
+ assertEquals("/SAP/PUBLIC/BC/NWDEMO_MODEL/IMAGES/Employee_1.png", properties.get("ImageUrl"));
+ }
+
+ @Test
+ public void readEntryNullProperty() throws Exception {
+ final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+ final String content = EMPLOYEE_1_XML.replace("<d:EntryDate>1999-01-01T00:00:00</d:EntryDate>",
+ "<d:EntryDate m:null='true' />");
+ InputStream contentBody = createContentAsStream(content);
+
+ final ODataEntry result =
+ new XmlEntityConsumer().readEntry(entitySet, contentBody, EntityProviderReadProperties.init().mergeSemantic(
+ true).build());
+
+ final Map<String, Object> properties = result.getProperties();
+ assertEquals(9, properties.size());
+ assertTrue(properties.containsKey("EntryDate"));
+ assertNull(properties.get("EntryDate"));
+ }
+
+ @Test(expected = EntityProviderException.class)
+ public void readEntryTooManyValues() throws Exception {
+ // prepare
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+ String content =
+ EMPLOYEE_1_XML.replace("<d:Age>52</d:Age>",
+ "<d:Age>52</d:Age><d:SomeUnknownTag>SomeUnknownValue</d:SomeUnknownTag>");
+ InputStream contentBody = createContentAsStream(content);
+
+ // execute
+ try {
+ new XmlEntityConsumer().readEntry(entitySet, contentBody, EntityProviderReadProperties.init()
+ .mergeSemantic(false).build());
+ } catch (EntityProviderException e) {
+ // do some assertions...
+ assertEquals(EntityProviderException.INVALID_PROPERTY.getKey(), e.getMessageReference().getKey());
+ assertEquals("SomeUnknownTag", e.getMessageReference().getContent().get(0));
+ // ...and then re-throw
+ throw e;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testReadEntryWithMerge() throws Exception {
+ // prepare
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+ String content = EMPLOYEE_1_XML.replace("<d:Age>52</d:Age>", "");
+ InputStream contentBody = createContentAsStream(content);
+
+ // execute
+ XmlEntityConsumer xec = new XmlEntityConsumer();
+ ODataEntry result =
+ xec.readEntry(entitySet, contentBody, EntityProvide
<TRUNCATED>
[6/6] git commit: [OLINGO-231] Several refactorings
Posted by mi...@apache.org.
[OLINGO-231] Several refactorings
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata2/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata2/commit/cb1ba468
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata2/tree/cb1ba468
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata2/diff/cb1ba468
Branch: refs/heads/OLINGO-231_PocForAndroid
Commit: cb1ba46855a469d7fc81d5a7e2f9b1b15187fcfa
Parents: 696288d
Author: Michael Bolz <mi...@sap.com>
Authored: Thu May 8 08:35:19 2014 +0200
Committer: Michael Bolz <mi...@sap.com>
Committed: Fri May 9 14:38:52 2014 +0200
----------------------------------------------------------------------
odata2-android/pom.xml | 9 +-
.../odata2/android/xml/AndroidXmlFactory.java | 17 +-
.../odata2/android/xml/AndroidXmlReader.java | 26 +-
.../odata2/android/xml/AndroidTestBase.java | 257 +
.../android/xml/AndroidXmlFactoryTest.java | 3 +-
.../android/xml/AndroidXmlReaderTest.java | 8 +-
.../android/xml/AtomEntryProducerTest.java | 849 ++
.../android/xml/AtomFeedProducerTest.java | 215 +
.../android/xml/XmlEntityConsumerTest.java | 2420 ++++
.../odata2/android/xml/XmlFeedConsumerTest.java | 155 +
.../src/test/resources/LargeEmployeeFeed.xml | 12556 +++++++++++++++++
.../src/test/resources/double_expanded_team.xml | 264 +
.../src/test/resources/expandedBuilding.xml | 61 +
.../src/test/resources/expanded_team.xml | 146 +
.../src/test/resources/feed_employees.xml | 247 +
.../src/test/resources/feed_employees_full.xml | 249 +
.../resources/feed_with_deleted_entries.xml | 40 +
.../src/test/resources/feed_with_delta_link.xml | 69 +
odata2-lib/odata-core/pom.xml | 5 -
.../olingo/odata2/core/commons/Base64.java | 589 +
.../olingo/odata2/core/commons/BaseNCodec.java | 350 +
.../apache/olingo/odata2/core/commons/Hex.java | 124 +
.../olingo/odata2/core/debug/DebugInfoBody.java | 2 +-
.../olingo/odata2/core/edm/EdmBinary.java | 9 +-
.../provider/EdmServiceMetadataImplProv.java | 25 +-
.../odata2/core/ep/BasicEntityProvider.java | 29 +-
.../odata2/core/debug/DebugInfoBodyTest.java | 2 +-
.../core/uri/expression/TestTokenizer.java | 9 +-
.../core/xml/JavaxStaxStreamFactoryTest.java | 13 +-
pom.xml | 1 -
30 files changed, 18668 insertions(+), 81 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb1ba468/odata2-android/pom.xml
----------------------------------------------------------------------
diff --git a/odata2-android/pom.xml b/odata2-android/pom.xml
index 8a8e1c3..614f558 100644
--- a/odata2-android/pom.xml
+++ b/odata2-android/pom.xml
@@ -34,7 +34,7 @@
<properties>
<version.android>4.1.1.4</version.android>
- <version.robolectric>2.2</version.robolectric>
+ <version.robolectric>2.3-SNAPSHOT</version.robolectric>
</properties>
<build>
@@ -96,6 +96,7 @@
<artifactId>olingo-odata2-core</artifactId>
<version>${project.version}</version>
</dependency>
+ <!-- Test dependencies -->
<dependency>
<groupId>org.apache.olingo</groupId>
<artifactId>olingo-odata2-testutil</artifactId>
@@ -112,6 +113,12 @@
<artifactId>robolectric</artifactId>
<version>${version.robolectric}</version>
<scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>com.android.support</groupId>
+ <artifactId>support-v4</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
<groupId>xmlunit</groupId>
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb1ba468/odata2-android/src/main/java/org/apache/olingo/odata2/android/xml/AndroidXmlFactory.java
----------------------------------------------------------------------
diff --git a/odata2-android/src/main/java/org/apache/olingo/odata2/android/xml/AndroidXmlFactory.java b/odata2-android/src/main/java/org/apache/olingo/odata2/android/xml/AndroidXmlFactory.java
index f2888a9..85eb024 100644
--- a/odata2-android/src/main/java/org/apache/olingo/odata2/android/xml/AndroidXmlFactory.java
+++ b/odata2-android/src/main/java/org/apache/olingo/odata2/android/xml/AndroidXmlFactory.java
@@ -18,13 +18,26 @@
******************************************************************************/
package org.apache.olingo.odata2.android.xml;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
import org.apache.olingo.odata2.api.xml.*;
import org.apache.olingo.odata2.core.xml.AbstractXmlStreamFactory;
public class AndroidXmlFactory extends AbstractXmlStreamFactory {
+ private static final String DEFAULT_CHARSET = "UTF-8";
+
@Override
- public XMLStreamReader createXMLStreamReader(Object content) throws XMLStreamException {
- return new AndroidXmlReader(content).setProperties(readProperties);
+ public XMLStreamReader createXMLStreamReader(Object content) throws XMLStreamException, EntityProviderException {
+ AndroidXmlReader reader = new AndroidXmlReader(content).setProperties(readProperties);
+
+ // verify charset encoding set in content is supported (if not set UTF-8 is used as defined in
+ // 'http://www.w3.org/TR/2008/REC-xml-20081126/')
+ String characterEncodingInContent = reader.getCharacterEncodingScheme();
+ if (characterEncodingInContent != null && !DEFAULT_CHARSET.equalsIgnoreCase(characterEncodingInContent)) {
+ throw new EntityProviderException(EntityProviderException
+ .UNSUPPORTED_CHARACTER_ENCODING.addContent(characterEncodingInContent));
+ }
+
+ return reader;
}
@Override
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb1ba468/odata2-android/src/main/java/org/apache/olingo/odata2/android/xml/AndroidXmlReader.java
----------------------------------------------------------------------
diff --git a/odata2-android/src/main/java/org/apache/olingo/odata2/android/xml/AndroidXmlReader.java b/odata2-android/src/main/java/org/apache/olingo/odata2/android/xml/AndroidXmlReader.java
index d793fe6..0bc1881 100644
--- a/odata2-android/src/main/java/org/apache/olingo/odata2/android/xml/AndroidXmlReader.java
+++ b/odata2-android/src/main/java/org/apache/olingo/odata2/android/xml/AndroidXmlReader.java
@@ -20,6 +20,7 @@ package org.apache.olingo.odata2.android.xml;
import java.io.IOException;
import java.io.InputStream;
+import java.util.HashMap;
import java.util.Map;
import org.apache.olingo.odata2.api.xml.NamespaceContext;
@@ -69,6 +70,10 @@ public class AndroidXmlReader implements XMLStreamReader {
return this;
}
+ public String getCharacterEncodingScheme() {
+ return parser.getInputEncoding();
+ }
+
@Override
public void close() throws XMLStreamException {
}
@@ -114,7 +119,6 @@ public class AndroidXmlReader implements XMLStreamReader {
text = parser.getText();
parser.next();
} catch (Exception e) {
- e.printStackTrace();
throw new XMLStreamException("Failure during step forward after 'getText'.", e);
}
return text;
@@ -137,18 +141,24 @@ public class AndroidXmlReader implements XMLStreamReader {
}
@Override
- public NamespaceContext getNamespaceContext() {
- String tmp = null;
+ public NamespaceContext getNamespaceContext() throws XMLStreamException {
+ final Map<String, String> prefix2Namespace;
try {
int depth = parser.getDepth();
- tmp = parser.getNamespacePrefix(depth);
+ int nsStart = parser.getNamespaceCount(depth-1);
+ int nsEnd = parser.getNamespaceCount(depth);
+ prefix2Namespace = new HashMap<String, String>(nsEnd-nsStart+1);
+ for (int i = nsStart; i < nsEnd; i++) {
+ String prefix = parser.getNamespacePrefix(i);
+ String namespace = parser.getNamespaceUri(i);
+ prefix2Namespace.put(namespace, prefix);
+ }
} catch (XmlPullParserException e) {
- e.printStackTrace();
+ throw new XMLStreamException("Got XmlPullParserException with message: " + e.getMessage(), e);
}
- final String prefix = tmp;
return new NamespaceContext() {
- public String getPrefix(String index) {
- return prefix;
+ public String getPrefix(String namespaceUri) {
+ return prefix2Namespace.get(namespaceUri);
}
};
}
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb1ba468/odata2-android/src/test/java/org/apache/olingo/odata2/android/xml/AndroidTestBase.java
----------------------------------------------------------------------
diff --git a/odata2-android/src/test/java/org/apache/olingo/odata2/android/xml/AndroidTestBase.java b/odata2-android/src/test/java/org/apache/olingo/odata2/android/xml/AndroidTestBase.java
new file mode 100644
index 0000000..fad1c12
--- /dev/null
+++ b/odata2-android/src/test/java/org/apache/olingo/odata2/android/xml/AndroidTestBase.java
@@ -0,0 +1,257 @@
+/*******************************************************************************
+ * 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.android.xml;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties;
+import org.apache.olingo.odata2.api.ep.callback.TombstoneCallback;
+import org.apache.olingo.odata2.core.ep.AtomEntityProvider;
+import org.custommonkey.xmlunit.SimpleNamespaceContext;
+import org.custommonkey.xmlunit.XMLUnit;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.*;
+
+import static org.apache.olingo.odata2.api.xml.XMLStreamReaderFactory.XML_STREAM_READER_FACTORY_CLASS;
+import static org.apache.olingo.odata2.api.xml.XMLStreamWriterFactory.XML_STREAM_WRITER_FACTORY_CLASS;
+
+/**
+ *
+*/
+@RunWith(RobolectricTestRunner.class)
+@Config(manifest=Config.NONE)
+public abstract class AndroidTestBase {
+
+ protected static final URI BASE_URI;
+
+ static {
+ try {
+ BASE_URI = new URI("http://host:80/service/");
+ } catch (URISyntaxException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ protected static final EntityProviderWriteProperties DEFAULT_PROPERTIES = EntityProviderWriteProperties.serviceRoot(
+ BASE_URI).build();
+
+ protected Map<String, Object> employeeData;
+
+ protected ArrayList<Map<String, Object>> employeesData;
+
+ protected Map<String, Object> photoData;
+
+ protected Map<String, Object> roomData;
+
+ protected Map<String, Object> buildingData;
+
+ protected ArrayList<Map<String, Object>> roomsData;
+
+ {
+ employeeData = new HashMap<String, Object>();
+
+ Calendar date = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+ date.clear();
+ date.set(1999, 0, 1);
+
+ employeeData.put("EmployeeId", "1");
+ employeeData.put("ImmageUrl", null);
+ employeeData.put("ManagerId", "1");
+ employeeData.put("Age", new Integer(52));
+ employeeData.put("RoomId", "1");
+ employeeData.put("EntryDate", date);
+ employeeData.put("TeamId", "42");
+ employeeData.put("EmployeeName", "Walter Winter");
+
+ Map<String, Object> locationData = new HashMap<String, Object>();
+ Map<String, Object> cityData = new HashMap<String, Object>();
+ cityData.put("PostalCode", "33470");
+ cityData.put("CityName", "Duckburg");
+ locationData.put("City", cityData);
+ locationData.put("Country", "Calisota");
+
+ employeeData.put("Location", locationData);
+
+ Map<String, Object> employeeData2 = new HashMap<String, Object>();
+ employeeData2.put("EmployeeId", "1");
+ employeeData2.put("ImmageUrl", null);
+ employeeData2.put("ManagerId", "1");
+ employeeData2.put("Age", new Integer(52));
+ employeeData2.put("RoomId", "1");
+ employeeData2.put("EntryDate", date);
+ employeeData2.put("TeamId", "42");
+ employeeData2.put("EmployeeName", "Walter Winter");
+
+ Map<String, Object> locationData2 = new HashMap<String, Object>();
+ Map<String, Object> cityData2 = new HashMap<String, Object>();
+ cityData2.put("PostalCode", "33470");
+ cityData2.put("CityName", "Duckburg");
+ locationData2.put("City", cityData2);
+ locationData2.put("Country", "Calisota");
+
+ employeeData2.put("Location", locationData2);
+
+ employeesData = new ArrayList<Map<String, Object>>();
+ employeesData.add(employeeData);
+ employeesData.add(employeeData2);
+
+ photoData = new HashMap<String, Object>();
+ photoData.put("Id", Integer.valueOf(1));
+ photoData.put("Name", "Mona Lisa");
+ photoData.put("Type", "image/png");
+ photoData.put(
+ "ImageUrl",
+ "http://www.mopo.de/image/view/2012/6/4/16548086,13385561,medRes,maxh,234,maxw,234," +
+ "Parodia_Mona_Lisa_Lego_Hamburger_Morgenpost.jpg");
+ Map<String, Object> imageData = new HashMap<String, Object>();
+ imageData.put("Image", new byte[] { 1, 2, 3, 4 });
+ imageData.put("getImageType", "image/png");
+ photoData.put("Image", imageData);
+ photoData.put("BinaryData", new byte[] { -1, -2, -3, -4 });
+ photoData.put("Содержание", "В лесу шумит водопад. Если он не торопится просп воды");
+
+ roomData = new HashMap<String, Object>();
+ roomData.put("Id", "1");
+ roomData.put("Name", "Neu Schwanstein");
+ roomData.put("Seats", new Integer(20));
+ roomData.put("Version", new Integer(3));
+
+ buildingData = new HashMap<String, Object>();
+ buildingData.put("Id", "1");
+ buildingData.put("Name", "WDF03");
+ buildingData.put("Image", "image");
+ }
+
+ protected void initializeRoomData(final int count) {
+ roomsData = new ArrayList<Map<String, Object>>();
+ for (int i = 1; i <= count; i++) {
+ HashMap<String, Object> tmp = new HashMap<String, Object>();
+ tmp.put("Id", "" + i);
+ tmp.put("Name", "Neu Schwanstein" + i);
+ tmp.put("Seats", new Integer(20));
+ tmp.put("Version", new Integer(3));
+ roomsData.add(tmp);
+ }
+ }
+
+ // CHECKSTYLE:OFF
+ @Before
+ public void setXmlFactory() throws Exception {
+ //
+ System.setProperty(XML_STREAM_WRITER_FACTORY_CLASS, AndroidXmlFactory.class.getName()); // NOSONAR
+ System.setProperty(XML_STREAM_READER_FACTORY_CLASS, AndroidXmlFactory.class.getName()); // NOSONAR
+ }
+ // CHECKSTYLE:ON
+
+ @Before
+ public void setXmlNamespacePrefixes() throws Exception {
+ //
+ Map<String, String> prefixMap = new HashMap<String, String>();
+ prefixMap.put("a", Edm.NAMESPACE_ATOM_2005);
+ prefixMap.put("d", Edm.NAMESPACE_D_2007_08);
+ prefixMap.put("m", Edm.NAMESPACE_M_2007_08);
+ prefixMap.put("xml", Edm.NAMESPACE_XML_1998);
+ prefixMap.put("ру", "http://localhost");
+ prefixMap.put("custom", "http://localhost");
+ prefixMap.put("at", TombstoneCallback.NAMESPACE_TOMBSTONE);
+ XMLUnit.setXpathNamespaceContext(new SimpleNamespaceContext(prefixMap));
+ }
+
+ protected AtomEntityProvider createAtomEntityProvider() throws EntityProviderException {
+ return new AtomEntityProvider();
+ }
+
+ protected String readFile(final String filename) throws IOException {
+ InputStream in = getFileAsStream(filename);
+
+ byte[] tmp = new byte[8192];
+ int count = in.read(tmp);
+ StringBuilder b = new StringBuilder();
+ while (count >= 0) {
+ b.append(new String(tmp, 0, count));
+ count = in.read(tmp);
+ }
+
+ return b.toString();
+ }
+
+ protected InputStream getFileAsStream(final String filename) throws IOException {
+ InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(filename);
+ if (in == null) {
+ throw new IOException("Requested file '" + filename + "' was not found.");
+ }
+ return in;
+ }
+
+ protected InputStream createContentAsStream(final String content) throws UnsupportedEncodingException {
+ return new ByteArrayInputStream(content.getBytes("UTF-8"));
+ }
+
+ /**
+ *
+ * @param content
+ * @param replaceWhitespaces if <code>true</code> all XML not necessary whitespaces between tags are
+ * @return
+ * @throws UnsupportedEncodingException
+ */
+ protected InputStream createContentAsStream(final String content, final boolean replaceWhitespaces)
+ throws UnsupportedEncodingException {
+ String contentForStream = content;
+ if (replaceWhitespaces) {
+ contentForStream = content.replaceAll(">\\s.<", "><");
+ }
+
+ return new ByteArrayInputStream(contentForStream.getBytes("UTF-8"));
+ }
+
+ /**
+ * Create a map with a 'String' to 'Class<?>' mapping based on given parameters.
+ * Therefore parameters MUST be a set of such pairs.
+ * As example an correct method call would be:
+ * <p>
+ * <code>
+ * createTypeMappings("someKey", Integer.class, "anotherKey", Long.class);
+ * </code>
+ * </p>
+ *
+ * @param firstKeyThenMappingClass
+ * @return
+ */
+ protected Map<String, Object> createTypeMappings(final Object... firstKeyThenMappingClass) {
+ Map<String, Object> typeMappings = new HashMap<String, Object>();
+ if (firstKeyThenMappingClass.length % 2 != 0) {
+ throw new IllegalArgumentException("Got odd number of parameters. Please read javadoc.");
+ }
+ for (int i = 0; i < firstKeyThenMappingClass.length; i += 2) {
+ String key = (String) firstKeyThenMappingClass[i];
+ Class<?> mappingClass = (Class<?>) firstKeyThenMappingClass[i + 1];
+ typeMappings.put(key, mappingClass);
+ }
+ return typeMappings;
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb1ba468/odata2-android/src/test/java/org/apache/olingo/odata2/android/xml/AndroidXmlFactoryTest.java
----------------------------------------------------------------------
diff --git a/odata2-android/src/test/java/org/apache/olingo/odata2/android/xml/AndroidXmlFactoryTest.java b/odata2-android/src/test/java/org/apache/olingo/odata2/android/xml/AndroidXmlFactoryTest.java
index e51c345..17364cd 100644
--- a/odata2-android/src/test/java/org/apache/olingo/odata2/android/xml/AndroidXmlFactoryTest.java
+++ b/odata2-android/src/test/java/org/apache/olingo/odata2/android/xml/AndroidXmlFactoryTest.java
@@ -24,7 +24,6 @@ import org.apache.olingo.odata2.api.xml.XMLStreamReader;
import org.apache.olingo.odata2.api.xml.XMLStreamWriter;
import org.apache.olingo.odata2.testutil.helper.StringHelper;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
@@ -62,7 +61,7 @@ public class AndroidXmlFactoryTest {
@Test
- @Ignore("Will work with robolectric version 2.3")
+// @Ignore("Will work with robolectric version 2.3")
public void createReader() throws Exception {
InputStream stream = StringHelper.encapsulate(BASIC_CONTENT);
XMLStreamReader xmlReader = streamFactory.createXMLStreamReader(stream);
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb1ba468/odata2-android/src/test/java/org/apache/olingo/odata2/android/xml/AndroidXmlReaderTest.java
----------------------------------------------------------------------
diff --git a/odata2-android/src/test/java/org/apache/olingo/odata2/android/xml/AndroidXmlReaderTest.java b/odata2-android/src/test/java/org/apache/olingo/odata2/android/xml/AndroidXmlReaderTest.java
index 51cebbb..af0d6a0 100644
--- a/odata2-android/src/test/java/org/apache/olingo/odata2/android/xml/AndroidXmlReaderTest.java
+++ b/odata2-android/src/test/java/org/apache/olingo/odata2/android/xml/AndroidXmlReaderTest.java
@@ -30,7 +30,6 @@ import org.apache.olingo.odata2.testutil.mock.MockFacade;
import org.custommonkey.xmlunit.SimpleNamespaceContext;
import org.custommonkey.xmlunit.XMLUnit;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
@@ -47,7 +46,7 @@ import static org.apache.olingo.odata2.api.xml.XMLStreamReaderFactory.XML_STREAM
*/
@RunWith(RobolectricTestRunner.class)
@Config(manifest=Config.NONE)
-@Ignore("Will work with robolectric version 2.3")
+// @Ignore("Will work with robolectric version 2.3")
public class AndroidXmlReaderTest {
private static final String BASIC_RESULT =
@@ -117,7 +116,6 @@ public class AndroidXmlReaderTest {
AndroidXmlReader xmlReader = new AndroidXmlReader(stream.asStream());
int[] expected = new int[]{
- XMLStreamConstants.START_DOCUMENT,
XMLStreamConstants.START_ELEMENT,
XMLStreamConstants.START_ELEMENT,
XMLStreamConstants.END_ELEMENT,
@@ -126,8 +124,8 @@ public class AndroidXmlReaderTest {
int pos = 0;
while(xmlReader.hasNext()) {
int elementId = xmlReader.next();
-// System.out.println("E: " + elementId);
- assertEquals(expected[pos++], elementId);
+ assertEquals("Unexpected type at position: " + pos,
+ expected[pos++], elementId);
}
}
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb1ba468/odata2-android/src/test/java/org/apache/olingo/odata2/android/xml/AtomEntryProducerTest.java
----------------------------------------------------------------------
diff --git a/odata2-android/src/test/java/org/apache/olingo/odata2/android/xml/AtomEntryProducerTest.java b/odata2-android/src/test/java/org/apache/olingo/odata2/android/xml/AtomEntryProducerTest.java
new file mode 100644
index 0000000..5f1ee53
--- /dev/null
+++ b/odata2-android/src/test/java/org/apache/olingo/odata2/android/xml/AtomEntryProducerTest.java
@@ -0,0 +1,849 @@
+/*******************************************************************************
+ * 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.android.xml;
+
+import org.apache.olingo.odata2.api.edm.*;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.exception.ODataMessageException;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.xml.XMLStreamException;
+import org.apache.olingo.odata2.core.commons.ContentType;
+import org.apache.olingo.odata2.core.ep.AtomEntityProvider;
+import org.apache.olingo.odata2.testutil.helper.StringHelper;
+import org.apache.olingo.odata2.testutil.helper.XMLUnitHelper;
+import org.apache.olingo.odata2.testutil.mock.MockFacade;
+import org.custommonkey.xmlunit.SimpleNamespaceContext;
+import org.custommonkey.xmlunit.XMLUnit;
+import org.custommonkey.xmlunit.exceptions.XpathException;
+import org.junit.Test;
+import org.robolectric.annotation.Config;
+import org.xml.sax.SAXException;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.custommonkey.xmlunit.XMLAssert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+/**
+ *
+ */
+@Config(manifest=Config.NONE)
+public class AtomEntryProducerTest extends AndroidTestBase {
+
+ @Test
+ public void noneSyndicationKeepInContentFalseMustNotShowInProperties() throws Exception {
+ // prepare Mock
+ EdmEntitySet employeesSet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+ EdmCustomizableFeedMappings employeeCustomPropertyMapping = mock(EdmCustomizableFeedMappings.class);
+ when(employeeCustomPropertyMapping.isFcKeepInContent()).thenReturn(Boolean.FALSE);
+ when(employeeCustomPropertyMapping.getFcNsPrefix()).thenReturn("customPre");
+ when(employeeCustomPropertyMapping.getFcNsUri()).thenReturn("http://customUri.com");
+ EdmTyped employeeEntryDateProperty = employeesSet.getEntityType().getProperty("EmployeeName");
+ when(((EdmProperty) employeeEntryDateProperty).getCustomizableFeedMappings()).thenReturn(
+ employeeCustomPropertyMapping);
+
+ Map<String, String> prefixMap = new HashMap<String, String>();
+ prefixMap.put("a", Edm.NAMESPACE_ATOM_2005);
+ prefixMap.put("d", Edm.NAMESPACE_D_2007_08);
+ prefixMap.put("m", Edm.NAMESPACE_M_2007_08);
+ prefixMap.put("xml", Edm.NAMESPACE_XML_1998);
+ prefixMap.put("customPre", "http://customUri.com");
+ XMLUnit.setXpathNamespaceContext(new SimpleNamespaceContext(prefixMap));
+
+ AtomEntityProvider ser = createAtomEntityProvider();
+ ODataResponse response = ser.writeEntry(employeesSet, employeeData, DEFAULT_PROPERTIES);
+ String xmlString = verifyResponse(response);
+
+ assertXpathExists("/a:entry/customPre:EmployeeName", xmlString);
+ assertXpathNotExists("/a:entry/m:properties/d:EmployeeName", xmlString);
+ }
+
+ @Test
+ public void noneSyndicationKeepInContentTrueMustShowInProperties() throws Exception {
+ // prepare Mock
+ EdmEntitySet employeesSet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+ EdmCustomizableFeedMappings employeeCustomPropertyMapping = mock(EdmCustomizableFeedMappings.class);
+ when(employeeCustomPropertyMapping.isFcKeepInContent()).thenReturn(Boolean.TRUE);
+ when(employeeCustomPropertyMapping.getFcNsPrefix()).thenReturn("customPre");
+ when(employeeCustomPropertyMapping.getFcNsUri()).thenReturn("http://customUri.com");
+ EdmTyped employeeEntryDateProperty = employeesSet.getEntityType().getProperty("EmployeeName");
+ when(((EdmProperty) employeeEntryDateProperty).getCustomizableFeedMappings()).thenReturn(
+ employeeCustomPropertyMapping);
+
+ Map<String, String> prefixMap = new HashMap<String, String>();
+ prefixMap.put("a", Edm.NAMESPACE_ATOM_2005);
+ prefixMap.put("d", Edm.NAMESPACE_D_2007_08);
+ prefixMap.put("m", Edm.NAMESPACE_M_2007_08);
+ prefixMap.put("xml", Edm.NAMESPACE_XML_1998);
+ prefixMap.put("customPre", "http://customUri.com");
+ XMLUnit.setXpathNamespaceContext(new SimpleNamespaceContext(prefixMap));
+
+ AtomEntityProvider ser = createAtomEntityProvider();
+ ODataResponse response = ser.writeEntry(employeesSet, employeeData, DEFAULT_PROPERTIES);
+ String xmlString = verifyResponse(response);
+
+ assertXpathExists("/a:entry/customPre:EmployeeName", xmlString);
+ assertXpathExists("/a:entry/m:properties/d:EmployeeName", xmlString);
+ }
+
+ @Test
+ public void noneSyndicationWithNullPrefix() throws Exception {
+ // prepare Mock
+ EdmEntitySet employeesSet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+ EdmCustomizableFeedMappings employeeCustomPropertyMapping = mock(EdmCustomizableFeedMappings.class);
+ when(employeeCustomPropertyMapping.isFcKeepInContent()).thenReturn(Boolean.TRUE);
+ when(employeeCustomPropertyMapping.getFcNsUri()).thenReturn("http://customUri.com");
+ EdmTyped employeeEntryDateProperty = employeesSet.getEntityType().getProperty("EmployeeName");
+ when(((EdmProperty) employeeEntryDateProperty).getCustomizableFeedMappings()).thenReturn(
+ employeeCustomPropertyMapping);
+
+ Map<String, String> prefixMap = new HashMap<String, String>();
+ prefixMap.put("a", Edm.NAMESPACE_ATOM_2005);
+ prefixMap.put("d", Edm.NAMESPACE_D_2007_08);
+ prefixMap.put("m", Edm.NAMESPACE_M_2007_08);
+ prefixMap.put("xml", Edm.NAMESPACE_XML_1998);
+ prefixMap.put("customPre", "http://customUri.com");
+ XMLUnit.setXpathNamespaceContext(new SimpleNamespaceContext(prefixMap));
+
+ AtomEntityProvider ser = createAtomEntityProvider();
+ boolean thrown = false;
+ try {
+ ser.writeEntry(employeesSet, employeeData, DEFAULT_PROPERTIES);
+ } catch (EntityProviderException e) {
+ verifyRootCause(EntityProviderException.class, EntityProviderException.INVALID_NAMESPACE.getKey(), e);
+ thrown = true;
+ }
+ if (!thrown) {
+ fail("Exception should have been thrown");
+ }
+ }
+
+ @Test
+ public void noneSyndicationWithNullUri() throws Exception {
+ // prepare Mock
+ EdmEntitySet employeesSet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+ EdmCustomizableFeedMappings employeeCustomPropertyMapping = mock(EdmCustomizableFeedMappings.class);
+ when(employeeCustomPropertyMapping.isFcKeepInContent()).thenReturn(Boolean.TRUE);
+ when(employeeCustomPropertyMapping.getFcNsPrefix()).thenReturn("customPre");
+ EdmTyped employeeEntryDateProperty = employeesSet.getEntityType().getProperty("EmployeeName");
+ when(((EdmProperty) employeeEntryDateProperty).getCustomizableFeedMappings()).thenReturn(
+ employeeCustomPropertyMapping);
+
+ Map<String, String> prefixMap = new HashMap<String, String>();
+ prefixMap.put("a", Edm.NAMESPACE_ATOM_2005);
+ prefixMap.put("d", Edm.NAMESPACE_D_2007_08);
+ prefixMap.put("m", Edm.NAMESPACE_M_2007_08);
+ prefixMap.put("xml", Edm.NAMESPACE_XML_1998);
+ prefixMap.put("customPre", "http://customUri.com");
+ XMLUnit.setXpathNamespaceContext(new SimpleNamespaceContext(prefixMap));
+
+ AtomEntityProvider ser = createAtomEntityProvider();
+ boolean thrown = false;
+ try {
+ ser.writeEntry(employeesSet, employeeData, DEFAULT_PROPERTIES);
+ } catch (EntityProviderException e) {
+ verifyRootCause(EntityProviderException.class, EntityProviderException.INVALID_NAMESPACE.getKey(), e);
+ thrown = true;
+ }
+ if (!thrown) {
+ fail("Exception should have been thrown");
+ }
+ }
+
+ @Test
+ public void noneSyndicationWithNullUriAndNullPrefix() throws Exception {
+ // prepare Mock
+ EdmEntitySet employeesSet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+ EdmCustomizableFeedMappings employeeCustomPropertyMapping = mock(EdmCustomizableFeedMappings.class);
+ when(employeeCustomPropertyMapping.isFcKeepInContent()).thenReturn(Boolean.TRUE);
+ EdmTyped employeeEntryDateProperty = employeesSet.getEntityType().getProperty("EmployeeName");
+ when(((EdmProperty) employeeEntryDateProperty).getCustomizableFeedMappings()).thenReturn(
+ employeeCustomPropertyMapping);
+
+ Map<String, String> prefixMap = new HashMap<String, String>();
+ prefixMap.put("a", Edm.NAMESPACE_ATOM_2005);
+ prefixMap.put("d", Edm.NAMESPACE_D_2007_08);
+ prefixMap.put("m", Edm.NAMESPACE_M_2007_08);
+ prefixMap.put("xml", Edm.NAMESPACE_XML_1998);
+ prefixMap.put("f", "http://customUri.com");
+ XMLUnit.setXpathNamespaceContext(new SimpleNamespaceContext(prefixMap));
+
+ AtomEntityProvider ser = createAtomEntityProvider();
+ boolean thrown = false;
+ try {
+ ser.writeEntry(employeesSet, employeeData, DEFAULT_PROPERTIES);
+ } catch (EntityProviderException e) {
+ verifyRootCause(EntityProviderException.class, EntityProviderException.INVALID_NAMESPACE.getKey(), e);
+ thrown = true;
+ }
+ if (!thrown) {
+ fail("Exception should have been thrown");
+ }
+ }
+
+ @Test
+ public void syndicationWithComplexProperty() throws Exception {
+ // prepare Mock
+ EdmEntitySet employeesSet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+ EdmCustomizableFeedMappings employeeCustomPropertyMapping = mock(EdmCustomizableFeedMappings.class);
+ when(employeeCustomPropertyMapping.isFcKeepInContent()).thenReturn(Boolean.TRUE);
+ when(employeeCustomPropertyMapping.getFcNsPrefix()).thenReturn("customPre");
+ when(employeeCustomPropertyMapping.getFcNsUri()).thenReturn("http://customUri.com");
+ EdmTyped employeeLocationProperty = employeesSet.getEntityType().getProperty("Location");
+ when(((EdmProperty) employeeLocationProperty).getCustomizableFeedMappings()).thenReturn(
+ employeeCustomPropertyMapping);
+
+ Map<String, String> prefixMap = new HashMap<String, String>();
+ prefixMap.put("a", Edm.NAMESPACE_ATOM_2005);
+ prefixMap.put("d", Edm.NAMESPACE_D_2007_08);
+ prefixMap.put("m", Edm.NAMESPACE_M_2007_08);
+ prefixMap.put("xml", Edm.NAMESPACE_XML_1998);
+ prefixMap.put("customPre", "http://customUri.com");
+ XMLUnit.setXpathNamespaceContext(new SimpleNamespaceContext(prefixMap));
+
+ AtomEntityProvider ser = createAtomEntityProvider();
+ ODataResponse response = ser.writeEntry(employeesSet, employeeData, DEFAULT_PROPERTIES);
+ String xmlString = verifyResponse(response);
+
+ assertXpathNotExists("/a:entry/customPre:Location", xmlString);
+ assertXpathExists("/a:entry/m:properties/d:Location", xmlString);
+ }
+
+ private void verifyRootCause(final Class<?> class1, final String key, final ODataMessageException e) {
+
+ Throwable thrownException = e;
+ Throwable lastFoundException = null;
+ if (e.getClass().equals(class1)) {
+ lastFoundException = e;
+ }
+
+ while (thrownException.getCause() != null) {
+ thrownException = thrownException.getCause();
+ if (thrownException.getClass().equals(class1)) {
+ lastFoundException = thrownException;
+ }
+ }
+
+ if (lastFoundException != null) {
+ ODataMessageException msgException = (ODataMessageException) lastFoundException;
+ assertEquals(key, msgException.getMessageReference().getKey());
+ } else {
+ fail("Exception of class: " + class1.getCanonicalName() + " in stacktrace not found.");
+ }
+ }
+
+ @Test
+ public void serializeAtomMediaResource() throws IOException, XpathException, SAXException, XMLStreamException,
+ ODataException {
+ AtomEntityProvider ser = createAtomEntityProvider();
+ ODataResponse response =
+ ser.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees"), employeeData,
+ DEFAULT_PROPERTIES);
+ String xmlString = verifyResponse(response);
+
+ assertXpathExists("/a:entry", xmlString);
+ assertXpathEvaluatesTo(BASE_URI.toASCIIString(), "/a:entry/@xml:base", xmlString);
+
+ assertXpathExists("/a:entry/a:content", xmlString);
+ assertXpathEvaluatesTo(ContentType.APPLICATION_OCTET_STREAM.toString(), "/a:entry/a:content/@type", xmlString);
+ assertXpathEvaluatesTo("Employees('1')/$value", "/a:entry/a:content/@src", xmlString);
+ assertXpathExists("/a:entry/m:properties", xmlString);
+
+ assertXpathExists("/a:entry/a:link[@href=\"Employees('1')/$value\"]", xmlString);
+ assertXpathExists("/a:entry/a:link[@rel='edit-media']", xmlString);
+ assertXpathExists("/a:entry/a:link[@type='application/octet-stream']", xmlString);
+
+ assertXpathExists("/a:entry/a:link[@href=\"Employees('1')\"]", xmlString);
+ assertXpathExists("/a:entry/a:link[@rel='edit']", xmlString);
+ assertXpathExists("/a:entry/a:link[@title='Employee']", xmlString);
+
+ // assert navigation link order
+ verifyTagOrdering(xmlString,
+ "link((?:(?!link).)*?)edit",
+ "link((?:(?!link).)*?)edit-media",
+ "link((?:(?!link).)*?)ne_Manager",
+ "link((?:(?!link).)*?)ne_Team",
+ "link((?:(?!link).)*?)ne_Room");
+ }
+
+ private String verifyResponse(final ODataResponse response) throws IOException {
+ assertNotNull(response);
+ assertNotNull(response.getEntity());
+ assertNull("EntityProvider should not set content header", response.getContentHeader());
+ String xmlString = StringHelper.inputStreamToString((InputStream) response.getEntity());
+ return xmlString;
+ }
+
+ @Test
+ public void serializeAtomMediaResourceWithMimeType() throws IOException, XpathException, SAXException,
+ XMLStreamException, ODataException {
+ AtomEntityProvider ser = createAtomEntityProvider();
+ EntityProviderWriteProperties properties =
+ EntityProviderWriteProperties.serviceRoot(BASE_URI).mediaResourceMimeType("abc").build();
+ ODataResponse response =
+ ser.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees"), employeeData,
+ properties);
+ String xmlString = verifyResponse(response);
+
+ assertXpathExists("/a:entry", xmlString);
+ assertXpathEvaluatesTo(BASE_URI.toASCIIString(), "/a:entry/@xml:base", xmlString);
+
+ assertXpathExists("/a:entry/a:content", xmlString);
+ assertXpathEvaluatesTo("abc", "/a:entry/a:content/@type", xmlString);
+ assertXpathEvaluatesTo("Employees('1')/$value", "/a:entry/a:content/@src", xmlString);
+ assertXpathExists("/a:entry/m:properties", xmlString);
+ }
+
+ /**
+ * Test serialization of empty syndication title property. EmployeeName is set to NULL after the update (which is
+ * allowed because EmployeeName has default Nullable behavior which is true).
+ * Write of an empty atom title tag is allowed within RFC4287 (http://tools.ietf.org/html/rfc4287#section-4.2.14).
+ */
+ @Test
+ public void serializeEmployeeWithNullSyndicationTitleProperty() throws IOException, XpathException, SAXException,
+ XMLStreamException, ODataException {
+ AtomEntityProvider ser = createAtomEntityProvider();
+ EntityProviderWriteProperties properties = EntityProviderWriteProperties.serviceRoot(BASE_URI).build();
+ employeeData.put("EmployeeName", null);
+ ODataResponse response =
+ ser.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees"), employeeData,
+ properties);
+ String xmlString = verifyResponse(response);
+
+ assertXpathExists("/a:entry/a:title", xmlString);
+ assertXpathEvaluatesTo("", "/a:entry/a:title", xmlString);
+
+ assertXpathExists("/a:entry", xmlString);
+ assertXpathEvaluatesTo(BASE_URI.toASCIIString(), "/a:entry/@xml:base", xmlString);
+
+ assertXpathExists("/a:entry/a:content", xmlString);
+ assertXpathEvaluatesTo("Employees('1')/$value", "/a:entry/a:content/@src", xmlString);
+ assertXpathExists("/a:entry/m:properties", xmlString);
+ }
+
+ @Test
+ public void serializeEmployeeAndCheckOrderOfTags() throws IOException, XpathException, SAXException,
+ XMLStreamException, ODataException {
+ AtomEntityProvider ser = createAtomEntityProvider();
+ EntityProviderWriteProperties properties =
+ EntityProviderWriteProperties.serviceRoot(BASE_URI).mediaResourceMimeType("abc").build();
+ ODataResponse response =
+ ser.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees"), employeeData,
+ properties);
+ String xmlString = verifyResponse(response);
+
+ assertXpathExists("/a:entry", xmlString);
+ assertXpathExists("/a:entry/a:content", xmlString);
+ // verify self link
+ assertXpathExists("/a:entry/a:link[@href=\"Employees('1')\"]", xmlString);
+ // verify content media link
+ assertXpathExists("/a:entry/a:link[@href=\"Employees('1')/$value\"]", xmlString);
+ // verify one navigation link
+ assertXpathExists("/a:entry/a:link[@title='ne_Manager']", xmlString);
+
+ // verify content
+ assertXpathExists("/a:entry/a:content[@type='abc']", xmlString);
+ // verify properties
+ assertXpathExists("/a:entry/m:properties", xmlString);
+ assertXpathEvaluatesTo("9", "count(/a:entry/m:properties/*)", xmlString);
+
+ // verify order of tags
+ verifyTagOrdering(xmlString, "id", "title", "updated", "category",
+ "link((?:(?!link).)*?)edit",
+ "link((?:(?!link).)*?)edit-media",
+ "link((?:(?!link).)*?)ne_Manager",
+ "content", "properties");
+ }
+
+ @Test
+ public void serializeEmployeeAndCheckOrderOfPropertyTags() throws IOException, XpathException, SAXException,
+ XMLStreamException, ODataException {
+ AtomEntityProvider ser = createAtomEntityProvider();
+ EntityProviderWriteProperties properties =
+ EntityProviderWriteProperties.serviceRoot(BASE_URI).mediaResourceMimeType("abc").build();
+ EdmEntitySet employeeEntitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+ ODataResponse response = ser.writeEntry(employeeEntitySet, employeeData, properties);
+ String xmlString = verifyResponse(response);
+
+ // log.debug(xmlString);
+
+ assertXpathExists("/a:entry", xmlString);
+ assertXpathExists("/a:entry/a:content", xmlString);
+ // verify properties
+ assertXpathExists("/a:entry/m:properties", xmlString);
+ assertXpathEvaluatesTo("9", "count(/a:entry/m:properties/*)", xmlString);
+
+ // verify order of tags
+ List<String> expectedPropertyNamesFromEdm = employeeEntitySet.getEntityType().getPropertyNames();
+ verifyTagOrdering(xmlString, expectedPropertyNamesFromEdm.toArray(new String[0]));
+ }
+
+ @Test
+ public void serializeEmployeeAndCheckKeepInContentFalse() throws IOException, XpathException, SAXException,
+ XMLStreamException, ODataException {
+ AtomEntityProvider ser = createAtomEntityProvider();
+ EntityProviderWriteProperties properties =
+ EntityProviderWriteProperties.serviceRoot(BASE_URI).mediaResourceMimeType("abc").build();
+ EdmEntitySet employeeEntitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+
+ // set "keepInContent" to false for EntryDate
+ EdmCustomizableFeedMappings employeeUpdatedMappings = mock(EdmCustomizableFeedMappings.class);
+ when(employeeUpdatedMappings.getFcTargetPath()).thenReturn(EdmTargetPath.SYNDICATION_UPDATED);
+ when(employeeUpdatedMappings.isFcKeepInContent()).thenReturn(Boolean.FALSE);
+ EdmTyped employeeEntryDateProperty = employeeEntitySet.getEntityType().getProperty("EntryDate");
+ when(((EdmProperty) employeeEntryDateProperty).getCustomizableFeedMappings()).thenReturn(employeeUpdatedMappings);
+
+ ODataResponse response = ser.writeEntry(employeeEntitySet, employeeData, properties);
+ String xmlString = verifyResponse(response);
+
+ assertXpathExists("/a:entry", xmlString);
+ assertXpathExists("/a:entry/a:content", xmlString);
+ // verify properties
+ assertXpathExists("/a:entry/m:properties", xmlString);
+ assertXpathEvaluatesTo("8", "count(/a:entry/m:properties/*)", xmlString);
+ //
+ assertXpathNotExists("/a:entry/m:properties/d:EntryDate", xmlString);
+
+ // verify order of tags
+ List<String> expectedPropertyNamesFromEdm =
+ new ArrayList<String>(employeeEntitySet.getEntityType().getPropertyNames());
+ expectedPropertyNamesFromEdm.remove(String.valueOf("EntryDate"));
+ verifyTagOrdering(xmlString, expectedPropertyNamesFromEdm.toArray(new String[0]));
+ }
+
+ @Test(expected = EntityProviderException.class)
+ public void serializeAtomEntryWithNullData() throws IOException, XpathException, SAXException, XMLStreamException,
+ ODataException {
+ final EntityProviderWriteProperties properties = EntityProviderWriteProperties.serviceRoot(BASE_URI).build();
+ AtomEntityProvider ser = createAtomEntityProvider();
+ ser.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms"), null, properties);
+ }
+
+ @Test(expected = EntityProviderException.class)
+ public void serializeAtomEntryWithEmptyHashMap() throws IOException, XpathException, SAXException,
+ XMLStreamException, ODataException {
+ final EntityProviderWriteProperties properties = EntityProviderWriteProperties.serviceRoot(BASE_URI).build();
+ AtomEntityProvider ser = createAtomEntityProvider();
+ ser.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms"),
+ new HashMap<String, Object>(), properties);
+ }
+
+ @Test
+ public void serializeAtomEntry() throws IOException, XpathException, SAXException, XMLStreamException,
+ ODataException {
+ final EntityProviderWriteProperties properties = EntityProviderWriteProperties.serviceRoot(BASE_URI).build();
+ AtomEntityProvider ser = createAtomEntityProvider();
+ ODataResponse response =
+ ser.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms"), roomData, properties);
+ String xmlString = verifyResponse(response);
+
+ assertXpathExists("/a:entry", xmlString);
+ assertXpathEvaluatesTo(BASE_URI.toASCIIString(), "/a:entry/@xml:base", xmlString);
+
+ assertXpathExists("/a:entry/a:content", xmlString);
+ assertXpathEvaluatesTo(ContentType.APPLICATION_XML.toString(), "/a:entry/a:content/@type", xmlString);
+
+ assertXpathExists("/a:entry/a:content/m:properties", xmlString);
+ }
+
+ @Test
+ public void serializeAtomEntryWithSimplePropertyTypeInformation() throws Exception {
+ final EntityProviderWriteProperties properties =
+ EntityProviderWriteProperties.serviceRoot(BASE_URI).includeSimplePropertyType(true).build();
+ AtomEntityProvider ser = createAtomEntityProvider();
+ ODataResponse response =
+ ser.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms"), roomData, properties);
+ String xmlString = verifyResponse(response);
+
+ assertXpathExists("/a:entry/a:content/m:properties", xmlString);
+ assertXpathExists("/a:entry/a:content/m:properties/d:Id[@m:type=\"Edm.String\"]", xmlString);
+ assertXpathExists("/a:entry/a:content/m:properties/d:Name[@m:type=\"Edm.String\"]", xmlString);
+ assertXpathExists("/a:entry/a:content/m:properties/d:Seats[@m:type=\"Edm.Int16\"]", xmlString);
+ assertXpathExists("/a:entry/a:content/m:properties/d:Version[@m:type=\"Edm.Int16\"]", xmlString);
+ }
+
+ @Test
+ public void serializeEntryId() throws IOException, XpathException, SAXException, XMLStreamException,
+ ODataException {
+ AtomEntityProvider ser = createAtomEntityProvider();
+ ODataResponse response =
+ ser.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees"), employeeData,
+ DEFAULT_PROPERTIES);
+ String xmlString = verifyResponse(response);
+
+ assertXpathExists("/a:entry", xmlString);
+ assertXpathEvaluatesTo(BASE_URI.toASCIIString(), "/a:entry/@xml:base", xmlString);
+ assertXpathExists("/a:entry/a:id", xmlString);
+ assertXpathEvaluatesTo(BASE_URI.toASCIIString() + "Employees('1')", "/a:entry/a:id/text()", xmlString);
+ }
+
+ @Test
+ public void serializeEntryTitle() throws Exception {
+ AtomEntityProvider ser = createAtomEntityProvider();
+ ODataResponse response =
+ ser.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees"), employeeData,
+ DEFAULT_PROPERTIES);
+ String xmlString = verifyResponse(response);
+
+ assertXpathExists("/a:entry/a:title", xmlString);
+ assertXpathEvaluatesTo("text", "/a:entry/a:title/@type", xmlString);
+ assertXpathEvaluatesTo((String) employeeData.get("EmployeeName"), "/a:entry/a:title/text()", xmlString);
+ }
+
+ @Test
+ public void serializeEntryUpdated() throws Exception {
+ AtomEntityProvider ser = createAtomEntityProvider();
+ ODataResponse response =
+ ser.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees"), employeeData,
+ DEFAULT_PROPERTIES);
+ String xmlString = verifyResponse(response);
+
+ assertXpathExists("/a:entry/a:updated", xmlString);
+ assertXpathEvaluatesTo("1999-01-01T00:00:00Z", "/a:entry/a:updated/text()", xmlString);
+ }
+
+ @Test
+ public void serializeIds() throws IOException, XpathException, SAXException, XMLStreamException,
+ ODataException {
+ AtomEntityProvider ser = createAtomEntityProvider();
+ ODataResponse response =
+ ser.writeEntry(MockFacade.getMockEdm().getEntityContainer("Container2").getEntitySet("Photos"), photoData,
+ DEFAULT_PROPERTIES);
+ String xmlString = verifyResponse(response);
+
+ assertXpathExists("/a:entry", xmlString);
+ assertXpathEvaluatesTo(BASE_URI.toASCIIString(), "/a:entry/@xml:base", xmlString);
+ assertXpathExists("/a:entry/a:id", xmlString);
+ assertXpathEvaluatesTo(BASE_URI.toASCIIString() + "Container2.Photos(Id=1,Type='image%2Fpng')",
+ "/a:entry/a:id/text()", xmlString);
+ }
+
+ @Test
+ public void serializeProperties() throws IOException, XpathException, SAXException, XMLStreamException,
+ ODataException {
+ AtomEntityProvider ser = createAtomEntityProvider();
+ ODataResponse response =
+ ser.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees"), employeeData,
+ DEFAULT_PROPERTIES);
+ String xmlString = verifyResponse(response);
+
+ assertXpathExists("/a:entry/m:properties", xmlString);
+ assertXpathEvaluatesTo((String) employeeData.get("RoomId"), "/a:entry/m:properties/d:RoomId/text()", xmlString);
+ assertXpathEvaluatesTo((String) employeeData.get("TeamId"), "/a:entry/m:properties/d:TeamId/text()", xmlString);
+ }
+
+ @Test
+ public void serializeWithValueEncoding() throws IOException, XpathException, SAXException, XMLStreamException,
+ ODataException {
+ photoData.put("Type", "< Ö >");
+
+ AtomEntityProvider ser = createAtomEntityProvider();
+ ODataResponse response =
+ ser.writeEntry(MockFacade.getMockEdm().getEntityContainer("Container2").getEntitySet("Photos"), photoData,
+ DEFAULT_PROPERTIES);
+ String xmlString = verifyResponse(response);
+
+ assertXpathExists("/a:entry", xmlString);
+ assertXpathEvaluatesTo(BASE_URI.toASCIIString(), "/a:entry/@xml:base", xmlString);
+ assertXpathExists("/a:entry/a:id", xmlString);
+ assertXpathEvaluatesTo(BASE_URI.toASCIIString() + "Container2.Photos(Id=1,Type='%3C%20%C3%96%20%3E')",
+ "/a:entry/a:id/text()", xmlString);
+ assertXpathEvaluatesTo("Container2.Photos(Id=1,Type='%3C%20%C3%96%20%3E')", "/a:entry/a:link/@href", xmlString);
+ }
+
+ @Test
+ public void serializeCategory() throws IOException, XpathException, SAXException, XMLStreamException,
+ ODataException {
+ AtomEntityProvider ser = createAtomEntityProvider();
+ ODataResponse response =
+ ser.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees"), employeeData,
+ DEFAULT_PROPERTIES);
+ String xmlString = verifyResponse(response);
+
+ assertXpathExists("/a:entry/a:category", xmlString);
+ assertXpathExists("/a:entry/a:category/@term", xmlString);
+ assertXpathExists("/a:entry/a:category/@scheme", xmlString);
+ assertXpathEvaluatesTo("RefScenario.Employee", "/a:entry/a:category/@term", xmlString);
+ assertXpathEvaluatesTo(Edm.NAMESPACE_SCHEME_2007_08, "/a:entry/a:category/@scheme", xmlString);
+ }
+
+ @Test
+ public void serializeETag() throws IOException, XpathException, SAXException, XMLStreamException,
+ ODataException {
+ AtomEntityProvider ser = createAtomEntityProvider();
+ ODataResponse response =
+ ser.writeEntry(MockFacade.getMockEdm().getEntityContainer("Container2").getEntitySet("Photos"), photoData,
+ DEFAULT_PROPERTIES);
+ String xmlString = verifyResponse(response);
+
+ assertXpathExists("/a:entry", xmlString);
+ assertXpathExists("/a:entry/@m:etag", xmlString);
+ assertXpathEvaluatesTo("W/\"1\"", "/a:entry/@m:etag", xmlString);
+ assertEquals("W/\"1\"", response.getETag());
+ }
+
+ @Test
+ public void serializeETagEncoding() throws IOException, XpathException, SAXException, XMLStreamException,
+ ODataException {
+ Edm edm = MockFacade.getMockEdm();
+ EdmTyped roomIdProperty = edm.getEntityType("RefScenario", "Room").getProperty("Id");
+ EdmFacets facets = mock(EdmFacets.class);
+ when(facets.getConcurrencyMode()).thenReturn(EdmConcurrencyMode.Fixed);
+ when(facets.getMaxLength()).thenReturn(3);
+ when(((EdmProperty) roomIdProperty).getFacets()).thenReturn(facets);
+
+ roomData.put("Id", "<\">");
+ AtomEntityProvider ser = createAtomEntityProvider();
+ ODataResponse response =
+ ser.writeEntry(edm.getDefaultEntityContainer().getEntitySet("Rooms"), roomData, DEFAULT_PROPERTIES);
+
+ assertNotNull(response);
+ assertNotNull(response.getEntity());
+ assertNull("EntityProvider should not set content header", response.getContentHeader());
+ assertEquals("W/\"<\">.3\"", response.getETag());
+
+ String xmlString = StringHelper.inputStreamToString((InputStream) response.getEntity());
+
+ assertXpathExists("/a:entry", xmlString);
+ assertXpathExists("/a:entry/@m:etag", xmlString);
+ assertXpathEvaluatesTo("W/\"<\">.3\"", "/a:entry/@m:etag", xmlString);
+ }
+
+ @Test
+ public void serializeCustomMapping() throws IOException, XpathException, SAXException, XMLStreamException,
+ ODataException {
+ AtomEntityProvider ser = createAtomEntityProvider();
+ ODataResponse response =
+ ser.writeEntry(MockFacade.getMockEdm().getEntityContainer("Container2").getEntitySet("Photos"), photoData,
+ DEFAULT_PROPERTIES);
+ String xmlString = verifyResponse(response);
+
+ assertXpathExists("/a:entry", xmlString);
+ assertXpathExists("/a:entry/ру:Содержание", xmlString);
+ assertXpathEvaluatesTo((String) photoData.get("Содержание"), "/a:entry/ру:Содержание/text()", xmlString);
+ verifyTagOrdering(xmlString, "category", "Содержание", "content", "properties");
+ }
+
+ @Test
+ public void testCustomProperties() throws Exception {
+ AtomEntityProvider ser = createAtomEntityProvider();
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getEntityContainer("Container2").getEntitySet("Photos");
+
+ ODataResponse response = ser.writeEntry(entitySet, photoData, DEFAULT_PROPERTIES);
+ String xmlString = verifyResponse(response);
+
+ assertXpathExists("/a:entry", xmlString);
+ assertXpathExists("/a:entry/custom:CustomProperty", xmlString);
+ assertXpathNotExists("/a:entry/custom:CustomProperty/text()", xmlString);
+ assertXpathEvaluatesTo("true", "/a:entry/custom:CustomProperty/@m:null", xmlString);
+ verifyTagOrdering(xmlString, "category", "Содержание", "CustomProperty", "content", "properties");
+ }
+
+ @Test
+ public void testKeepInContentNull() throws Exception {
+ AtomEntityProvider ser = createAtomEntityProvider();
+ EdmEntitySet entitySet = MockFacade.getMockEdm().getEntityContainer("Container2").getEntitySet("Photos");
+
+ EdmProperty customProperty = (EdmProperty) entitySet.getEntityType().getProperty("CustomProperty");
+ when(customProperty.getCustomizableFeedMappings().isFcKeepInContent()).thenReturn(null);
+
+ ODataResponse response = ser.writeEntry(entitySet, photoData, DEFAULT_PROPERTIES);
+ String xmlString = verifyResponse(response);
+
+ assertXpathExists("/a:entry", xmlString);
+ assertXpathExists("/a:entry/custom:CustomProperty", xmlString);
+ assertXpathNotExists("/a:entry/custom:CustomProperty/text()", xmlString);
+ assertXpathEvaluatesTo("true", "/a:entry/custom:CustomProperty/@m:null", xmlString);
+ assertXpathExists("/a:entry/m:properties/d:CustomProperty", xmlString);
+ verifyTagOrdering(xmlString, "category", "Содержание", "CustomProperty", "content", "properties");
+ }
+
+ @Test
+ public void serializeAtomMediaResourceLinks() throws IOException, XpathException, SAXException, XMLStreamException,
+ ODataException {
+ AtomEntityProvider ser = createAtomEntityProvider();
+ ODataResponse response =
+ ser.writeEntry(MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees"), employeeData,
+ DEFAULT_PROPERTIES);
+ String xmlString = verifyResponse(response);
+
+ String rel = Edm.NAMESPACE_REL_2007_08 + "ne_Manager";
+
+ assertXpathExists("/a:entry/a:link[@href=\"Employees('1')/ne_Manager\"]", xmlString);
+ assertXpathExists("/a:entry/a:link[@rel='" + rel + "']", xmlString);
+ assertXpathExists("/a:entry/a:link[@type='application/atom+xml;type=entry']", xmlString);
+ assertXpathExists("/a:entry/a:link[@title='ne_Manager']", xmlString);
+ }
+
+ @Test
+ public void additionalLink() throws Exception {
+ Map<String, Map<String, Object>> links = new HashMap<String, Map<String, Object>>();
+ links.put("nr_Building", buildingData);
+ final ODataResponse response = createAtomEntityProvider().writeEntry(
+ MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms"), roomData,
+ EntityProviderWriteProperties.serviceRoot(BASE_URI).additionalLinks(links).build());
+ final String xmlString = verifyResponse(response);
+
+ assertXpathExists("/a:entry/a:link[@title='nr_Building']", xmlString);
+ assertXpathNotExists("/a:entry/a:link[@href=\"Rooms('1')/nr_Building\"]", xmlString);
+ assertXpathExists("/a:entry/a:link[@href=\"Buildings('1')\"]", xmlString);
+ assertXpathNotExists("/a:entry/a:link[@type='application/atom+xml;type=entry']", xmlString);
+ }
+
+ @Test
+ public void additionalLinkToOneOfMany() throws Exception {
+ Map<String, Map<String, Object>> links = new HashMap<String, Map<String, Object>>();
+ links.put("nr_Employees", employeeData);
+ final ODataResponse response = createAtomEntityProvider().writeEntry(
+ MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms"), roomData,
+ EntityProviderWriteProperties.serviceRoot(BASE_URI).additionalLinks(links).build());
+ final String xmlString = verifyResponse(response);
+
+ assertXpathExists("/a:entry/a:link[@title='nr_Employees']", xmlString);
+ assertXpathNotExists("/a:entry/a:link[@href=\"Rooms('1')/nr_Employees\"]", xmlString);
+ assertXpathExists("/a:entry/a:link[@href=\"Employees('1')\"]", xmlString);
+ assertXpathNotExists("/a:entry/a:link[@type='application/atom+xml;type=feed']", xmlString);
+ }
+
+ @Test
+ public void serializeWithCustomSrcAttributeOnEmployee() throws Exception {
+ AtomEntityProvider ser = createAtomEntityProvider();
+ Map<String, Object> localEmployeeData = new HashMap<String, Object>(employeeData);
+ String mediaResourceSourceKey = "~src";
+ localEmployeeData.put(mediaResourceSourceKey, "http://localhost:8080/images/image1");
+ EdmEntitySet employeesSet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+ EdmMapping mapping = employeesSet.getEntityType().getMapping();
+ when(mapping.getMediaResourceSourceKey()).thenReturn(mediaResourceSourceKey);
+
+ ODataResponse response = ser.writeEntry(employeesSet, localEmployeeData, DEFAULT_PROPERTIES);
+ String xmlString = verifyResponse(response);
+
+ assertXpathExists(
+ "/a:entry/a:link[@href=\"Employees('1')/$value\" and" +
+ " @rel=\"edit-media\" and @type=\"application/octet-stream\"]", xmlString);
+ assertXpathExists("/a:entry/a:content[@type=\"application/octet-stream\"]", xmlString);
+ assertXpathExists("/a:entry/a:content[@src=\"http://localhost:8080/images/image1\"]", xmlString);
+ }
+
+ @Test
+ public void serializeWithCustomSrcAndTypeAttributeOnEmployee() throws Exception {
+ AtomEntityProvider ser = createAtomEntityProvider();
+ Map<String, Object> localEmployeeData = new HashMap<String, Object>(employeeData);
+ String mediaResourceSourceKey = "~src";
+ localEmployeeData.put(mediaResourceSourceKey, "http://localhost:8080/images/image1");
+ String mediaResourceMimeTypeKey = "~type";
+ localEmployeeData.put(mediaResourceMimeTypeKey, "image/jpeg");
+ EdmEntitySet employeesSet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+ EdmMapping mapping = employeesSet.getEntityType().getMapping();
+ when(mapping.getMediaResourceSourceKey()).thenReturn(mediaResourceSourceKey);
+ when(mapping.getMediaResourceMimeTypeKey()).thenReturn(mediaResourceMimeTypeKey);
+ when(mapping.getMimeType()).thenReturn(null);
+ ODataResponse response = ser.writeEntry(employeesSet, localEmployeeData, DEFAULT_PROPERTIES);
+ String xmlString = verifyResponse(response);
+
+ assertXpathExists(
+ "/a:entry/a:link[@href=\"Employees('1')/$value\" and" +
+ " @rel=\"edit-media\" and @type=\"image/jpeg\"]", xmlString);
+ assertXpathExists("/a:entry/a:content[@type=\"image/jpeg\"]", xmlString);
+ assertXpathExists("/a:entry/a:content[@src=\"http://localhost:8080/images/image1\"]", xmlString);
+ }
+
+ @Test
+ public void serializeWithCustomSrcAttributeOnRoom() throws Exception {
+ AtomEntityProvider ser = createAtomEntityProvider();
+ Map<String, Object> localRoomData = new HashMap<String, Object>(roomData);
+ String mediaResourceSourceKey = "~src";
+ localRoomData.put(mediaResourceSourceKey, "http://localhost:8080/images/image1");
+ EdmEntitySet roomsSet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+ EdmEntityType roomType = roomsSet.getEntityType();
+ EdmMapping mapping = mock(EdmMapping.class);
+ when(roomType.getMapping()).thenReturn(mapping);
+ when(mapping.getMediaResourceSourceKey()).thenReturn(mediaResourceSourceKey);
+
+ ODataResponse response = ser.writeEntry(roomsSet, localRoomData, DEFAULT_PROPERTIES);
+ String xmlString = verifyResponse(response);
+
+ assertXpathNotExists(
+ "/a:entry/a:link[@href=\"Rooms('1')/$value\" and" +
+ " @rel=\"edit-media\" and @type=\"application/octet-stream\"]", xmlString);
+ assertXpathNotExists("/a:entry/a:content[@type=\"application/octet-stream\"]", xmlString);
+ assertXpathNotExists("/a:entry/a:content[@src=\"http://localhost:8080/images/image1\"]", xmlString);
+ }
+
+ @Test
+ public void serializeWithCustomSrcAndTypeAttributeOnRoom() throws Exception {
+ AtomEntityProvider ser = createAtomEntityProvider();
+ Map<String, Object> localRoomData = new HashMap<String, Object>(roomData);
+ String mediaResourceSourceKey = "~src";
+ localRoomData.put(mediaResourceSourceKey, "http://localhost:8080/images/image1");
+ String mediaResourceMimeTypeKey = "~type";
+ localRoomData.put(mediaResourceMimeTypeKey, "image/jpeg");
+ EdmEntitySet roomsSet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+ EdmEntityType roomType = roomsSet.getEntityType();
+ EdmMapping mapping = mock(EdmMapping.class);
+ when(roomType.getMapping()).thenReturn(mapping);
+ when(mapping.getMediaResourceSourceKey()).thenReturn(mediaResourceSourceKey);
+ when(mapping.getMediaResourceMimeTypeKey()).thenReturn(mediaResourceMimeTypeKey);
+
+ ODataResponse response = ser.writeEntry(roomsSet, localRoomData, DEFAULT_PROPERTIES);
+ String xmlString = verifyResponse(response);
+
+ assertXpathNotExists(
+ "/a:entry/a:link[@href=\"Rooms('1')/$value\" and" +
+ " @rel=\"edit-media\" and @type=\"image/jpeg\"]", xmlString);
+ assertXpathNotExists("/a:entry/a:content[@type=\"image/jpeg\"]", xmlString);
+ assertXpathNotExists("/a:entry/a:content[@src=\"http://localhost:8080/images/image1\"]", xmlString);
+ }
+
+ @Test
+ public void assureGetMimeTypeWinsOverGetMediaResourceMimeTypeKey() throws Exception {
+ // Keep this test till version 1.2
+ AtomEntityProvider ser = createAtomEntityProvider();
+ Map<String, Object> localEmployeeData = new HashMap<String, Object>(employeeData);
+ String mediaResourceMimeTypeKey = "~type";
+ localEmployeeData.put(mediaResourceMimeTypeKey, "wrong");
+ String originalMimeTypeKey = "~originalType";
+ localEmployeeData.put(originalMimeTypeKey, "right");
+ EdmEntitySet employeesSet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+ EdmMapping mapping = employeesSet.getEntityType().getMapping();
+ when(mapping.getMediaResourceMimeTypeKey()).thenReturn(mediaResourceMimeTypeKey);
+ when(mapping.getMimeType()).thenReturn(originalMimeTypeKey);
+ ODataResponse response = ser.writeEntry(employeesSet, localEmployeeData, DEFAULT_PROPERTIES);
+ String xmlString = verifyResponse(response);
+
+ assertXpathExists("/a:entry/a:content[@type=\"right\"]", xmlString);
+ assertXpathNotExists("/a:entry/a:content[@type=\"wrong\"]", xmlString);
+ }
+
+ private void verifyTagOrdering(final String xmlString, final String... toCheckTags) {
+ XMLUnitHelper.verifyTagOrdering(xmlString, toCheckTags);
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb1ba468/odata2-android/src/test/java/org/apache/olingo/odata2/android/xml/AtomFeedProducerTest.java
----------------------------------------------------------------------
diff --git a/odata2-android/src/test/java/org/apache/olingo/odata2/android/xml/AtomFeedProducerTest.java b/odata2-android/src/test/java/org/apache/olingo/odata2/android/xml/AtomFeedProducerTest.java
new file mode 100644
index 0000000..eaef473
--- /dev/null
+++ b/odata2-android/src/test/java/org/apache/olingo/odata2/android/xml/AtomFeedProducerTest.java
@@ -0,0 +1,215 @@
+/*******************************************************************************
+ * 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.android.xml;
+
+import org.apache.olingo.odata2.api.commons.InlineCount;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetUriInfo;
+import org.apache.olingo.odata2.core.ep.AtomEntityProvider;
+import org.apache.olingo.odata2.testutil.helper.StringHelper;
+import org.apache.olingo.odata2.testutil.mock.MockFacade;
+import org.junit.Before;
+import org.junit.Test;
+import org.robolectric.annotation.Config;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+
+import static org.custommonkey.xmlunit.XMLAssert.*;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+/**
+ *
+ */
+@Config(manifest=Config.NONE)
+public class AtomFeedProducerTest extends AndroidTestBase {
+
+ private GetEntitySetUriInfo view;
+
+ @Before
+ public void before() throws Exception {
+ initializeRoomData(1);
+
+ view = mock(GetEntitySetUriInfo.class);
+
+ EdmEntitySet set = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+ when(view.getTargetEntitySet()).thenReturn(set);
+ }
+
+ @Test
+ public void testWithIncludeSimplePropertyTypes() throws Exception {
+ AtomEntityProvider ser = createAtomEntityProvider();
+ EntityProviderWriteProperties properties =
+ EntityProviderWriteProperties.serviceRoot(BASE_URI).includeSimplePropertyType(true).build();
+ ODataResponse response = ser.writeFeed(view.getTargetEntitySet(), roomsData, properties);
+ String xmlString = verifyResponse(response);
+
+ assertXpathExists("/a:feed", xmlString);
+ assertXpathExists("/a:feed/a:entry/a:content/m:properties", xmlString);
+ assertXpathExists("/a:feed/a:entry/a:content/m:properties/d:Id[@m:type=\"Edm.String\"]", xmlString);
+ assertXpathExists("/a:feed/a:entry/a:content/m:properties/d:Name[@m:type=\"Edm.String\"]", xmlString);
+ assertXpathExists("/a:feed/a:entry/a:content/m:properties/d:Seats[@m:type=\"Edm.Int16\"]", xmlString);
+ assertXpathExists("/a:feed/a:entry/a:content/m:properties/d:Version[@m:type=\"Edm.Int16\"]", xmlString);
+ }
+
+ @Test
+ public void testFeedNamespaces() throws Exception {
+ AtomEntityProvider ser = createAtomEntityProvider();
+ EntityProviderWriteProperties properties =
+ EntityProviderWriteProperties.serviceRoot(BASE_URI).mediaResourceMimeType("mediatype").build();
+ ODataResponse response = ser.writeFeed(view.getTargetEntitySet(), roomsData, properties);
+ String xmlString = verifyResponse(response);
+
+ assertXpathExists("/a:feed", xmlString);
+ assertXpathEvaluatesTo(BASE_URI.toASCIIString(), "/a:feed/@xml:base", xmlString);
+ }
+
+ @Test
+ public void testSelfLink() throws Exception {
+ AtomEntityProvider ser = createAtomEntityProvider();
+ EntityProviderWriteProperties properties =
+ EntityProviderWriteProperties.serviceRoot(BASE_URI).mediaResourceMimeType("mediatype").build();
+ ODataResponse response = ser.writeFeed(view.getTargetEntitySet(), roomsData, properties);
+ String xmlString = verifyResponse(response);
+
+ assertXpathExists("/a:feed/a:link[@rel='self']", xmlString);
+ assertXpathEvaluatesTo("Rooms", "/a:feed/a:link[@rel='self']/@href", xmlString);
+ assertXpathEvaluatesTo("Rooms", "/a:feed/a:link[@rel='self']/@title", xmlString);
+ }
+
+ @Test
+ public void testCustomSelfLink() throws Exception {
+ String customLink = "Test";
+ AtomEntityProvider ser = createAtomEntityProvider();
+ EntityProviderWriteProperties properties =
+ EntityProviderWriteProperties.serviceRoot(BASE_URI).mediaResourceMimeType("mediatype").selfLink(
+ new URI(customLink)).build();
+ ODataResponse response = ser.writeFeed(view.getTargetEntitySet(), roomsData, properties);
+ String xmlString = verifyResponse(response);
+
+ assertXpathExists("/a:feed/a:link[@rel='self']", xmlString);
+ assertXpathEvaluatesTo(customLink, "/a:feed/a:link[@rel='self']/@href", xmlString);
+ assertXpathEvaluatesTo("Rooms", "/a:feed/a:link[@rel='self']/@title", xmlString);
+ }
+
+ @Test
+ public void testFeedMandatoryParts() throws Exception {
+ AtomEntityProvider ser = createAtomEntityProvider();
+ EntityProviderWriteProperties properties =
+ EntityProviderWriteProperties.serviceRoot(BASE_URI).mediaResourceMimeType("mediatype").build();
+ ODataResponse response = ser.writeFeed(view.getTargetEntitySet(), roomsData, properties);
+ String xmlString = verifyResponse(response);
+
+ assertXpathExists("/a:feed/a:id", xmlString);
+ assertXpathEvaluatesTo(BASE_URI.toASCIIString() + "Rooms", "/a:feed/a:id/text()", xmlString);
+
+ assertXpathExists("/a:feed/a:title", xmlString);
+ assertXpathEvaluatesTo("Rooms", "/a:feed/a:title/text()", xmlString);
+
+ assertXpathExists("/a:feed/a:updated", xmlString);
+ assertXpathExists("/a:feed/a:author", xmlString);
+ assertXpathExists("/a:feed/a:author/a:name", xmlString);
+ }
+
+ private String verifyResponse(final ODataResponse response) throws IOException {
+ assertNotNull(response);
+ assertNotNull(response.getEntity());
+ assertNull("EntityProvider should not set content header", response.getContentHeader());
+ String xmlString = StringHelper.inputStreamToString((InputStream) response.getEntity());
+ return xmlString;
+ }
+
+ @Test
+ public void testInlineCountAllpages() throws Exception {
+ initializeRoomData(20);
+
+ AtomEntityProvider ser = createAtomEntityProvider();
+ EntityProviderWriteProperties properties = EntityProviderWriteProperties.serviceRoot(BASE_URI)
+ .mediaResourceMimeType("mediatype")
+ .inlineCount(Integer.valueOf(103))
+ .inlineCountType(InlineCount.ALLPAGES)
+ .build();
+ ODataResponse response = ser.writeFeed(view.getTargetEntitySet(), roomsData, properties);
+ String xmlString = verifyResponse(response);
+
+ assertXpathExists("/a:feed/m:count", xmlString);
+ assertXpathEvaluatesTo("103", "/a:feed/m:count/text()", xmlString);
+ }
+
+ @Test
+ public void testInlineCountNone() throws Exception {
+ when(view.getInlineCount()).thenReturn(InlineCount.NONE);
+
+ AtomEntityProvider ser = createAtomEntityProvider();
+ EntityProviderWriteProperties properties =
+ EntityProviderWriteProperties.serviceRoot(BASE_URI).mediaResourceMimeType("mediatype").build();
+ ODataResponse response = ser.writeFeed(view.getTargetEntitySet(), roomsData, properties);
+ String xmlString = verifyResponse(response);
+
+ assertXpathNotExists("/a:feed/m:count", xmlString);
+ }
+
+ @Test
+ public void testNextLink() throws Exception {
+ when(view.getInlineCount()).thenReturn(InlineCount.NONE);
+
+ AtomEntityProvider ser = createAtomEntityProvider();
+ EntityProviderWriteProperties properties = EntityProviderWriteProperties.serviceRoot(BASE_URI)
+ .mediaResourceMimeType("mediatype")
+ .nextLink("http://thisisanextlink")
+ .build();
+ ODataResponse response = ser.writeFeed(view.getTargetEntitySet(), roomsData, properties);
+ String xmlString = verifyResponse(response);
+
+ assertXpathExists("/a:feed/a:link[@rel='next']", xmlString);
+ assertXpathEvaluatesTo("http://thisisanextlink", "/a:feed/a:link[@rel='next']/@href", xmlString);
+ }
+
+ @Test(expected = EntityProviderException.class)
+ public void testInlineCountInvalid() throws Exception {
+ AtomEntityProvider ser = createAtomEntityProvider();
+ EntityProviderWriteProperties properties =
+ EntityProviderWriteProperties.serviceRoot(BASE_URI).mediaResourceMimeType("mediatype").inlineCountType(
+ InlineCount.ALLPAGES).build();
+ ser.writeFeed(view.getTargetEntitySet(), roomsData, properties);
+ }
+
+ @Test
+ public void testEntries() throws Exception {
+ initializeRoomData(103);
+
+ AtomEntityProvider ser = createAtomEntityProvider();
+ EntityProviderWriteProperties properties =
+ EntityProviderWriteProperties.serviceRoot(BASE_URI).mediaResourceMimeType("mediatype").build();
+ ODataResponse response = ser.writeFeed(view.getTargetEntitySet(), roomsData, properties);
+ String xmlString = verifyResponse(response);
+
+ assertXpathExists("/a:feed/a:entry[1]", xmlString);
+ assertXpathExists("/a:feed/a:entry[2]", xmlString);
+ assertXpathExists("/a:feed/a:entry[103]", xmlString);
+ }
+
+}
[2/6] [OLINGO-231] Several refactorings
Posted by mi...@apache.org.
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb1ba468/odata2-android/src/test/resources/double_expanded_team.xml
----------------------------------------------------------------------
diff --git a/odata2-android/src/test/resources/double_expanded_team.xml b/odata2-android/src/test/resources/double_expanded_team.xml
new file mode 100644
index 0000000..7a82144
--- /dev/null
+++ b/odata2-android/src/test/resources/double_expanded_team.xml
@@ -0,0 +1,264 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+<entry xml:base="http://some.host.com/service.root/"
+ 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">
+ <id>http://some.host.com/service.root/Teams('1')</id>
+ <title type="text">Team 1</title>
+ <updated>2013-03-21T12:44:28Z</updated>
+ <category term="RefScenario.Team"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Teams('1')" rel="edit" title="Team" />
+ <link href="Teams('1')/nt_Employees"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/nt_Employees"
+ type="application/atom+xml;type=feed" title="nt_Employees">
+ <m:inline>
+ <feed xml:base="http://some.host.com/service.root/">
+ <id>http://some.host.com/service.root/Employees</id>
+ <title type="text">Employees</title>
+ <updated>2013-03-21T12:44:28Z</updated>
+ <author>
+ <name />
+ </author>
+ <link href="Employees" rel="self" title="Employees" />
+ <entry>
+ <id>http://some.host.com/service.root/Employees('1')
+ </id>
+ <title type="text">Walter Winter</title>
+ <updated>1999-01-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('1')" rel="edit" title="Employee" />
+ <link href="Employees('1')/$value" rel="edit-media" type="image/jpeg" />
+ <link href="Employees('1')/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+ type="application/atom+xml;type=entry" title="ne_Manager" />
+ <link href="Employees('1')/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+ type="application/atom+xml;type=entry" title="ne_Team">
+ <m:inline>
+ <entry xml:base="http://some.host.com/service.root/">
+ <id>http://some.host.com/service.root/Teams('1')
+ </id>
+ <title type="text">Team 1</title>
+ <updated>2013-03-21T12:44:28Z</updated>
+ <category term="RefScenario.Team"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Teams('1')" rel="edit" title="Team" />
+ <link href="Teams('1')/nt_Employees"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/nt_Employees"
+ type="application/atom+xml;type=feed" title="nt_Employees" />
+ <link href="Teams('1')/$links/nt_Employees"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/nt_Employees"
+ type="application/xml" title="nt_Employees" />
+ <content type="application/xml">
+ <m:properties>
+ <d:Id>1</d:Id>
+ <d:Name>Team 1</d:Name>
+ <d:isScrumTeam>false</d:isScrumTeam>
+ </m:properties>
+ </content>
+ </entry>
+ </m:inline>
+ </link>
+ <link href="Employees('1')/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+ type="application/atom+xml;type=entry" title="ne_Room" />
+ <link href="Employees('1')/$links/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Manager"
+ type="application/xml" title="ne_Manager" />
+ <link href="Employees('1')/$links/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Team"
+ type="application/xml" title="ne_Team" />
+ <link href="Employees('1')/$links/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Room"
+ type="application/xml" title="ne_Room" />
+ <content type="image/jpeg" src="Employees('1')/$value" />
+ <m:properties>
+ <d:EmployeeId>1</d:EmployeeId>
+ <d:EmployeeName>Walter Winter</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>1</d:RoomId>
+ <d:TeamId>1</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69124</d:PostalCode>
+ <d:CityName>Heidelberg</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>52</d:Age>
+ <d:EntryDate>1999-01-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('1')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>http://some.host.com/service.root/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="image/jpeg" />
+ <link href="Employees('2')/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+ type="application/atom+xml;type=entry" title="ne_Manager" />
+ <link href="Employees('2')/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+ type="application/atom+xml;type=entry" title="ne_Team">
+ <m:inline>
+ <entry xml:base="http://some.host.com/service.root/">
+ <id>http://some.host.com/service.root/Teams('1')</id>
+ <title type="text">Team 1</title>
+ <updated>2013-03-21T12:44:28Z</updated>
+ <category term="RefScenario.Team"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Teams('1')" rel="edit" title="Team" />
+ <link href="Teams('1')/nt_Employees"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/nt_Employees"
+ type="application/atom+xml;type=feed" title="nt_Employees" />
+ <link href="Teams('1')/$links/nt_Employees"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/nt_Employees"
+ type="application/xml" title="nt_Employees" />
+ <content type="application/xml">
+ <m:properties>
+ <d:Id>1</d:Id>
+ <d:Name>Team 1</d:Name>
+ <d:isScrumTeam>false</d:isScrumTeam>
+ </m:properties>
+ </content>
+ </entry>
+ </m:inline>
+ </link>
+ <link href="Employees('2')/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+ type="application/atom+xml;type=entry" title="ne_Room" />
+ <link href="Employees('2')/$links/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Manager"
+ type="application/xml" title="ne_Manager" />
+ <link href="Employees('2')/$links/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Team"
+ type="application/xml" title="ne_Team" />
+ <link href="Employees('2')/$links/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Room"
+ type="application/xml" title="ne_Room" />
+ <content type="image/jpeg" 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://some.host.com/service.root/Employees('3')</id>
+ <title type="text">Jonathan Smith</title>
+ <updated>2013-03-21T12:44:28Z</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="image/jpeg" />
+ <link href="Employees('3')/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager"
+ type="application/atom+xml;type=entry" title="ne_Manager" />
+ <link href="Employees('3')/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team"
+ type="application/atom+xml;type=entry" title="ne_Team">
+ <m:inline>
+ <entry xml:base="http://some.host.com/service.root/">
+ <id>http://some.host.com/service.root/Teams('1')</id>
+ <title type="text">Team 1</title>
+ <updated>2013-03-21T12:44:28Z</updated>
+ <category term="RefScenario.Team"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Teams('1')" rel="edit" title="Team" />
+ <link href="Teams('1')/nt_Employees"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/nt_Employees"
+ type="application/atom+xml;type=feed" title="nt_Employees" />
+ <link href="Teams('1')/$links/nt_Employees"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/nt_Employees"
+ type="application/xml" title="nt_Employees" />
+ <content type="application/xml">
+ <m:properties>
+ <d:Id>1</d:Id>
+ <d:Name>Team 1</d:Name>
+ <d:isScrumTeam>false</d:isScrumTeam>
+ </m:properties>
+ </content>
+ </entry>
+ </m:inline>
+ </link>
+ <link href="Employees('3')/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room"
+ type="application/atom+xml;type=entry" title="ne_Room" />
+ <link href="Employees('3')/$links/ne_Manager"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Manager"
+ type="application/xml" title="ne_Manager" />
+ <link href="Employees('3')/$links/ne_Team"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Team"
+ type="application/xml" title="ne_Team" />
+ <link href="Employees('3')/$links/ne_Room"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Room"
+ type="application/xml" title="ne_Room" />
+ <content type="image/jpeg" 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>
+ </feed>
+ </m:inline>
+ </link>
+ <link href="Teams('1')/$links/nt_Employees"
+ rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/nt_Employees"
+ type="application/xml" title="nt_Employees" />
+ <content type="application/xml">
+ <m:properties>
+ <d:Id>1</d:Id>
+ <d:Name>Team 1</d:Name>
+ <d:isScrumTeam>false</d:isScrumTeam>
+ </m:properties>
+ </content>
+</entry>
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb1ba468/odata2-android/src/test/resources/expandedBuilding.xml
----------------------------------------------------------------------
diff --git a/odata2-android/src/test/resources/expandedBuilding.xml b/odata2-android/src/test/resources/expandedBuilding.xml
new file mode 100644
index 0000000..e637969
--- /dev/null
+++ b/odata2-android/src/test/resources/expandedBuilding.xml
@@ -0,0 +1,61 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!--
+ 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.
+-->
+<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://some.host.com/service.root/ReferenceScenario.svc/">
+ <id>http://some.host.com/service.root/ReferenceScenario.svc/Rooms('1')</id>
+ <title type="text">Room 1</title>
+ <updated>2013-04-19T10:58:03.646Z</updated>
+ <category term="RefScenario.Room" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Rooms('1')" rel="edit" title="Room" />
+ <link href="Rooms('1')/nr_Employees" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/nr_Employees"
+ title="nr_Employees" type="application/atom+xml; type=feed" />
+ <link href="Rooms('1')/nr_Building" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/nr_Building"
+ title="nr_Building" type="application/atom+xml; type=entry">
+ <m:inline>
+ <entry>
+ <id>http://some.host.com/service.root/ReferenceScenario.svc/Buildings('1')</id>
+ <title type="text">Buildings</title>
+ <updated>2013-04-19T10:58:03.646Z</updated>
+ <author>
+ <name>Building 1</name>
+ </author>
+ <category term="RefScenario.Building" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Buildings('1')" rel="edit" title="Building" />
+ <link href="Buildings('1')/nb_Rooms" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/nb_Rooms"
+ title="nb_Rooms" type="application/atom+xml; type=feed" />
+ <content type="application/xml">
+ <m:properties>
+ <d:Id>1</d:Id>
+ <d:Name>Building 1</d:Name>
+ <d:Image m:null="true" />
+ </m:properties>
+ </content>
+ </entry>
+ </m:inline>
+ </link>
+ <content type="application/xml">
+ <m:properties>
+ <d:Id>1</d:Id>
+ <d:Name>Room 1</d:Name>
+ <d:Seats>1</d:Seats>
+ <d:Version>1</d:Version>
+ </m:properties>
+ </content>
+</entry>
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb1ba468/odata2-android/src/test/resources/expanded_team.xml
----------------------------------------------------------------------
diff --git a/odata2-android/src/test/resources/expanded_team.xml b/odata2-android/src/test/resources/expanded_team.xml
new file mode 100644
index 0000000..c18a78b
--- /dev/null
+++ b/odata2-android/src/test/resources/expanded_team.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+<entry xml:base="http://some.host.com/service.root/"
+ 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">
+ <id>http://some.host.com/service.root/Teams('1')</id>
+ <title type="text">Team 1</title>
+ <updated>2013-03-14T11:16:48Z</updated>
+ <category term="RefScenario.Team" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+ <link href="Teams('1')" rel="edit" title="Team"/>
+ <link href="Teams('1')/nt_Employees" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/nt_Employees" type="application/atom+xml;type=feed" title="nt_Employees">
+ <m:inline>
+ <feed xml:base="http://some.host.com/service.root/">
+ <id>http://some.host.com/service.root/Employees</id>
+ <title type="text">Employees</title>
+ <updated>2013-03-14T11:16:48Z</updated>
+ <author>
+ <name/>
+ </author>
+ <link href="Employees" rel="self" title="Employees"/>
+ <entry>
+ <id>http://some.host.com/service.root/Employees('1')</id>
+ <title type="text">Walter Winter</title>
+ <updated>1999-01-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
+ <link href="Employees('1')" rel="edit" title="Employee"/>
+ <link href="Employees('1')/$value" rel="edit-media" type="image/jpeg"/>
+ <link href="Employees('1')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" type="application/atom+xml;type=entry" title="ne_Manager"/>
+ <link href="Employees('1')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" type="application/atom+xml;type=entry" title="ne_Team"/>
+ <link href="Employees('1')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" type="application/atom+xml;type=entry" title="ne_Room"/>
+ <link href="Employees('1')/$links/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Manager" type="application/xml" title="ne_Manager"/>
+ <link href="Employees('1')/$links/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Team" type="application/xml" title="ne_Team"/>
+ <link href="Employees('1')/$links/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Room" type="application/xml" title="ne_Room"/>
+ <content type="image/jpeg" src="Employees('1')/$value"/>
+ <m:properties>
+ <d:EmployeeId>1</d:EmployeeId>
+ <d:EmployeeName>Walter Winter</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>1</d:RoomId>
+ <d:TeamId>1</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69124</d:PostalCode>
+ <d:CityName>Heidelberg</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>52</d:Age>
+ <d:EntryDate>1999-01-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('1')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>http://some.host.com/service.root/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="image/jpeg"/>
+ <link href="Employees('2')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" type="application/atom+xml;type=entry" title="ne_Manager"/>
+ <link href="Employees('2')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" type="application/atom+xml;type=entry" title="ne_Team"/>
+ <link href="Employees('2')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" type="application/atom+xml;type=entry" title="ne_Room"/>
+ <link href="Employees('2')/$links/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Manager" type="application/xml" title="ne_Manager"/>
+ <link href="Employees('2')/$links/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Team" type="application/xml" title="ne_Team"/>
+ <link href="Employees('2')/$links/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Room" type="application/xml" title="ne_Room"/>
+ <content type="image/jpeg" 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://some.host.com/service.root/Employees('3')</id>
+ <title type="text">Jonathan Smith</title>
+ <updated>2013-03-14T11:16:48Z</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="image/jpeg"/>
+ <link href="Employees('3')/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager" type="application/atom+xml;type=entry" title="ne_Manager"/>
+ <link href="Employees('3')/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team" type="application/atom+xml;type=entry" title="ne_Team"/>
+ <link href="Employees('3')/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room" type="application/atom+xml;type=entry" title="ne_Room"/>
+ <link href="Employees('3')/$links/ne_Manager" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Manager" type="application/xml" title="ne_Manager"/>
+ <link href="Employees('3')/$links/ne_Team" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Team" type="application/xml" title="ne_Team"/>
+ <link href="Employees('3')/$links/ne_Room" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/ne_Room" type="application/xml" title="ne_Room"/>
+ <content type="image/jpeg" 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>
+ </feed>
+ </m:inline>
+ </link>
+ <link href="Teams('1')/$links/nt_Employees" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/nt_Employees" type="application/xml" title="nt_Employees"/>
+ <content type="application/xml">
+ <m:properties>
+ <d:Id>1</d:Id>
+ <d:Name>Team 1</d:Name>
+ <d:isScrumTeam>false</d:isScrumTeam>
+ </m:properties>
+ </content>
+</entry>
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb1ba468/odata2-android/src/test/resources/feed_employees.xml
----------------------------------------------------------------------
diff --git a/odata2-android/src/test/resources/feed_employees.xml b/odata2-android/src/test/resources/feed_employees.xml
new file mode 100644
index 0000000..53e124f
--- /dev/null
+++ b/odata2-android/src/test/resources/feed_employees.xml
@@ -0,0 +1,247 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!--
+ 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.
+-->
+<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://some.host.com/service.root/ReferenceScenario.svc/">
+ <id>http://some.host.com/service.root/ReferenceScenario.svc/Employees</id>
+ <title type="text">Employees</title>
+ <updated>2013-04-23T11:46:14.926Z</updated>
+ <author>
+ <name />
+ </author>
+ <link href="Employees" rel="self" title="Employees" />
+ <entry>
+ <id>http://some.host.com/service.root/ReferenceScenario.svc/Employees('1')</id>
+ <title type="text">Walter Winter</title>
+ <updated>1999-01-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('1')" rel="edit" title="Employee" />
+ <link href="Employees('1')/$value" rel="edit-media" type="application/octet-stream" />
+ <link href="Employees('1')/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('1')/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('1')/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('1')/$value" />
+ <m:properties>
+ <d:EmployeeId>1</d:EmployeeId>
+ <d:EmployeeName>Walter Winter</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>1</d:RoomId>
+ <d:TeamId>1</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69124</d:PostalCode>
+ <d:CityName>Heidelberg</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>52</d:Age>
+ <d:EntryDate>1999-01-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('1')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>http://some.host.com/service.root/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://some.host.com/service.root/ReferenceScenario.svc/Employees('3')</id>
+ <title type="text">Jonathan Smith</title>
+ <updated>2013-04-23T11:46:14.928Z</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://some.host.com/service.root/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://some.host.com/service.root/ReferenceScenario.svc/Employees('5')</id>
+ <title type="text">John Field</title>
+ <updated>2001-02-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('5')" rel="edit" title="Employee" />
+ <link href="Employees('5')/$value" rel="edit-media" type="application/octet-stream" />
+ <link href="Employees('5')/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('5')/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('5')/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('5')/$value" />
+ <m:properties>
+ <d:EmployeeId>5</d:EmployeeId>
+ <d:EmployeeName>John Field</d:EmployeeName>
+ <d:ManagerId>3</d:ManagerId>
+ <d:RoomId>3</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>42</d:Age>
+ <d:EntryDate>2001-02-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('5')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>http://some.host.com/service.root/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>
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb1ba468/odata2-android/src/test/resources/feed_employees_full.xml
----------------------------------------------------------------------
diff --git a/odata2-android/src/test/resources/feed_employees_full.xml b/odata2-android/src/test/resources/feed_employees_full.xml
new file mode 100644
index 0000000..fc78f99
--- /dev/null
+++ b/odata2-android/src/test/resources/feed_employees_full.xml
@@ -0,0 +1,249 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!--
+ 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.
+-->
+<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://some.host.com/service.root/ReferenceScenario.svc/">
+ <id>http://some.host.com/service.root/ReferenceScenario.svc/Employees</id>
+ <title type="text">Employees</title>
+ <updated>2013-04-23T11:46:14.926Z</updated>
+ <author>
+ <name />
+ </author>
+ <m:count>6</m:count>
+ <link href="Employees" rel="self" title="Employees" />
+ <link href="http://thisisanextlink" rel="next"/>
+ <entry>
+ <id>http://some.host.com/service.root/ReferenceScenario.svc/Employees('1')</id>
+ <title type="text">Walter Winter</title>
+ <updated>1999-01-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('1')" rel="edit" title="Employee" />
+ <link href="Employees('1')/$value" rel="edit-media" type="application/octet-stream" />
+ <link href="Employees('1')/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('1')/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('1')/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('1')/$value" />
+ <m:properties>
+ <d:EmployeeId>1</d:EmployeeId>
+ <d:EmployeeName>Walter Winter</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>1</d:RoomId>
+ <d:TeamId>1</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69124</d:PostalCode>
+ <d:CityName>Heidelberg</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>52</d:Age>
+ <d:EntryDate>1999-01-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('1')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>http://some.host.com/service.root/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://some.host.com/service.root/ReferenceScenario.svc/Employees('3')</id>
+ <title type="text">Jonathan Smith</title>
+ <updated>2013-04-23T11:46:14.928Z</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://some.host.com/service.root/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://some.host.com/service.root/ReferenceScenario.svc/Employees('5')</id>
+ <title type="text">John Field</title>
+ <updated>2001-02-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('5')" rel="edit" title="Employee" />
+ <link href="Employees('5')/$value" rel="edit-media" type="application/octet-stream" />
+ <link href="Employees('5')/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('5')/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('5')/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('5')/$value" />
+ <m:properties>
+ <d:EmployeeId>5</d:EmployeeId>
+ <d:EmployeeName>John Field</d:EmployeeName>
+ <d:ManagerId>3</d:ManagerId>
+ <d:RoomId>3</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>42</d:Age>
+ <d:EntryDate>2001-02-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('5')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <entry>
+ <id>http://some.host.com/service.root/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>
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb1ba468/odata2-android/src/test/resources/feed_with_deleted_entries.xml
----------------------------------------------------------------------
diff --git a/odata2-android/src/test/resources/feed_with_deleted_entries.xml b/odata2-android/src/test/resources/feed_with_deleted_entries.xml
new file mode 100644
index 0000000..78c187e
--- /dev/null
+++ b/odata2-android/src/test/resources/feed_with_deleted_entries.xml
@@ -0,0 +1,40 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!-- 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. -->
+<feed xmlns="http://www.w3.org/2005/Atom" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
+ xmlns:at="http://purl.org/atompub/tombstones/1.0" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
+ xml:base="https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/">
+ <id>https://olingoodata.neo.ondemand.com:443/com.sap.olingo.web/ReferenceScenario.svc/Rooms</id>
+ <title type="text">Rooms</title>
+ <updated>2014-01-21T09:15:52.473Z</updated>
+ <author>
+ <name />
+ </author>
+ <link href="Rooms" rel="self" title="Rooms" />
+ <entry m:etag="W/"1"">
+ <id>http://host:123/odata/Rooms('1')</id>
+ <title type="text">Room 1</title>
+ <updated>2014-01-21T09:15:52.474Z</updated>
+ <category term="RefScenario.Room" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Rooms('1')" rel="edit" title="Room" />
+ <link href="Rooms('1')/nr_Employees" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/nr_Employees"
+ title="nr_Employees" type="application/atom+xml;type=feed" />
+ <link href="Rooms('1')/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>1</d:Id>
+ <d:Name>Room 1</d:Name>
+ <d:Seats>1</d:Seats>
+ <d:Version>1</d:Version>
+ </m:properties>
+ </content>
+ </entry>
+ <at:deleted-entry ref="http://host:123/odata/Rooms('2')" when="2014-01-14T18:11:06.682+01:00" />
+ <link href="http://host:123/odata/Rooms?$skiptoken=97" rel="delta" />
+</feed>
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb1ba468/odata2-android/src/test/resources/feed_with_delta_link.xml
----------------------------------------------------------------------
diff --git a/odata2-android/src/test/resources/feed_with_delta_link.xml b/odata2-android/src/test/resources/feed_with_delta_link.xml
new file mode 100644
index 0000000..bb73341
--- /dev/null
+++ b/odata2-android/src/test/resources/feed_with_delta_link.xml
@@ -0,0 +1,69 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!--
+ 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.
+-->
+<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"
+ xmlns:at="http://purl.org/atompub/tombstones/1.0"
+ xml:base="http://some.host.com/service.root/ReferenceScenario.svc/">
+ <id>http://some.host.com/service.root/ReferenceScenario.svc/Employees</id>
+ <title type="text">Employees</title>
+ <updated>2013-04-23T11:46:14.926Z</updated>
+ <author>
+ <name />
+ </author>
+ <link href="Employees" rel="self" title="Employees" />
+ <entry>
+ <id>http://some.host.com/service.root/ReferenceScenario.svc/Employees('1')</id>
+ <title type="text">Walter Winter</title>
+ <updated>1999-01-01T00:00:00Z</updated>
+ <category term="RefScenario.Employee"
+ scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
+ <link href="Employees('1')" rel="edit" title="Employee" />
+ <link href="Employees('1')/$value" rel="edit-media" type="application/octet-stream" />
+ <link href="Employees('1')/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('1')/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('1')/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('1')/$value" />
+ <m:properties>
+ <d:EmployeeId>1</d:EmployeeId>
+ <d:EmployeeName>Walter Winter</d:EmployeeName>
+ <d:ManagerId>1</d:ManagerId>
+ <d:RoomId>1</d:RoomId>
+ <d:TeamId>1</d:TeamId>
+ <d:Location m:type="RefScenario.c_Location">
+ <d:City m:type="RefScenario.c_City">
+ <d:PostalCode>69124</d:PostalCode>
+ <d:CityName>Heidelberg</d:CityName>
+ </d:City>
+ <d:Country>Germany</d:Country>
+ </d:Location>
+ <d:Age>52</d:Age>
+ <d:EntryDate>1999-01-01T00:00:00</d:EntryDate>
+ <d:ImageUrl>Employees('1')/$value</d:ImageUrl>
+ </m:properties>
+ </entry>
+ <link href="http://thisisadeltalink" rel="delta"/>
+</feed>
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb1ba468/odata2-lib/odata-core/pom.xml
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/pom.xml b/odata2-lib/odata-core/pom.xml
index 44c9232..b4f612a 100644
--- a/odata2-lib/odata-core/pom.xml
+++ b/odata2-lib/odata-core/pom.xml
@@ -176,11 +176,6 @@
<version>${project.version}</version>
</dependency>
<dependency>
- <groupId>commons-codec</groupId>
- <artifactId>commons-codec</artifactId>
- <version>${commonscodec.version}</version>
- </dependency>
- <dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>${gson.version}</version>
http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb1ba468/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/Base64.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/Base64.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/Base64.java
new file mode 100644
index 0000000..629312b
--- /dev/null
+++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/Base64.java
@@ -0,0 +1,589 @@
+/*
+ * 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.commons;
+
+/**
+ * Provides Base64 encoding and decoding as defined by <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>.
+ * <p/>
+ * <p>
+ * This class implements section <cite>6.8. Base64 Content-Transfer-Encoding</cite> from RFC 2045 <cite>Multipurpose
+ * Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies</cite> by Freed and Borenstein.
+ * </p>
+ * <p>
+ * The class can be parameterized in the following manner with various constructors:
+ * <ul>
+ * <li>URL-safe mode: Default off.</li>
+ * <li>Line length: Default 76. Line length that aren't multiples of 4 will still essentially end up being multiples of
+ * 4 in the encoded data.
+ * <li>Line separator: Default is CRLF ("\r\n")</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Since this class operates directly on byte streams, and not character streams, it is hard-coded to only encode/decode
+ * character encodings which are compatible with the lower 127 ASCII chart (ISO-8859-1, Windows-1252, UTF-8, etc).
+ * </p>
+ * <p>
+ * This class is not thread-safe. Each thread should use its own instance.
+ * </p>
+ *
+ * @author Apache Software Foundation
+ * @version $Revision: 1201529 $
+ * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>
+ * @since 1.0
+ */
+public class Base64 extends BaseNCodec {
+
+ /**
+ * BASE32 characters are 6 bits in length.
+ * They are formed by taking a block of 3 octets to form a 24-bit string,
+ * which is converted into 4 BASE64 characters.
+ */
+ private static final int BITS_PER_ENCODED_BYTE = 6;
+ private static final int BYTES_PER_UNENCODED_BLOCK = 3;
+ private static final int BYTES_PER_ENCODED_BLOCK = 4;
+
+ /**
+ * Chunk separator per RFC 2045 section 2.1.
+ * <p/>
+ * <p>
+ * N.B. The next major release may break compatibility and make this field private.
+ * </p>
+ *
+ * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045 section 2.1</a>
+ */
+ static final byte[] CHUNK_SEPARATOR = {'\r', '\n'};
+
+ /**
+ * This array is a lookup table that translates 6-bit positive integer index values into their "Base64 Alphabet"
+ * equivalents as specified in Table 1 of RFC 2045.
+ * <p/>
+ * Thanks to "commons" project in ws.apache.org for this code.
+ * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
+ */
+ private static final byte[] STANDARD_ENCODE_TABLE = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
+ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
+ };
+
+ /**
+ * This is a copy of the STANDARD_ENCODE_TABLE above, but with + and /
+ * changed to - and _ to make the encoded Base64 results more URL-SAFE.
+ * This table is only used when the Base64's mode is set to URL-SAFE.
+ */
+ private static final byte[] URL_SAFE_ENCODE_TABLE = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
+ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'
+ };
+
+ /**
+ * This array is a lookup table that translates Unicode characters drawn from the "Base64 Alphabet" (as specified in
+ * Table 1 of RFC 2045) into their 6-bit positive integer equivalents. Characters that are not in the Base64
+ * alphabet but fall within the bounds of the array are translated to -1.
+ * <p/>
+ * Note: '+' and '-' both decode to 62. '/' and '_' both decode to 63. This means decoder seamlessly handles both
+ * URL_SAFE and STANDARD base64. (The encoder, on the other hand, needs to know ahead of time what to emit).
+ * <p/>
+ * Thanks to "commons" project in ws.apache.org for this code.
+ * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
+ */
+ private static final byte[] DECODE_TABLE = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 62, -1, 63, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, -1, -1, -1, -1, 63, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
+ };
+
+ /**
+ * Base64 uses 6-bit fields.
+ */
+ /**
+ * Mask used to extract 6 bits, used when encoding
+ */
+ private static final int MASK_6BITS = 0x3f;
+
+ // The static final fields above are used for the original static byte[] methods on Base64.
+ // The private member fields below are used with the new streaming approach, which requires
+ // some state be preserved between calls of encode() and decode().
+
+ /**
+ * Encode table to use: either STANDARD or URL_SAFE. Note: the DECODE_TABLE above remains static because it is able
+ * to decode both STANDARD and URL_SAFE streams, but the encodeTable must be a member variable so we can switch
+ * between the two modes.
+ */
+ private final byte[] encodeTable;
+
+ // Only one decode table currently; keep for consistency with Base32 code
+ private final byte[] decodeTable = DECODE_TABLE;
+
+ /**
+ * Line separator for encoding. Not used when decoding. Only used if lineLength > 0.
+ */
+ private final byte[] lineSeparator;
+
+ /**
+ * Convenience variable to help us determine when our buffer is going to run out of room and needs resizing.
+ * <code>decodeSize = 3 + lineSeparator.length;</code>
+ */
+ private final int decodeSize;
+
+ /**
+ * Convenience variable to help us determine when our buffer is going to run out of room and needs resizing.
+ * <code>encodeSize = 4 + lineSeparator.length;</code>
+ */
+ private final int encodeSize;
+
+ /**
+ * Place holder for the bytes we're dealing with for our based logic.
+ * Bitwise operations store and extract the encoding or decoding from this variable.
+ */
+ private int bitWorkArea;
+
+ /**
+ * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
+ * <p>
+ * When encoding the line length is 0 (no chunking), and the encoding table is STANDARD_ENCODE_TABLE.
+ * </p>
+ * <p/>
+ * <p>
+ * When decoding all variants are supported.
+ * </p>
+ */
+ public Base64() {
+ this(0);
+ }
+
+ /**
+ * Creates a Base64 codec used for decoding (all modes) and encoding in the given URL-safe mode.
+ * <p>
+ * When encoding the line length is 76, the line separator is CRLF, and the encoding table is STANDARD_ENCODE_TABLE.
+ * </p>
+ * <p/>
+ * <p>
+ * When decoding all variants are supported.
+ * </p>
+ *
+ * @param urlSafe if <code>true</code>, URL-safe encoding is used. In most cases this should be set to
+ * <code>false</code>.
+ * @since 1.4
+ */
+ public Base64(boolean urlSafe) {
+ this(MIME_CHUNK_SIZE, CHUNK_SEPARATOR, urlSafe);
+ }
+
+ /**
+ * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
+ * <p>
+ * When encoding the line length is given in the constructor, the line separator is CRLF, and the encoding table is
+ * STANDARD_ENCODE_TABLE.
+ * </p>
+ * <p>
+ * Line lengths that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data.
+ * </p>
+ * <p>
+ * When decoding all variants are supported.
+ * </p>
+ *
+ * @param lineLength Each line of encoded data will be at most of the given length (rounded down to nearest
+ * multiple of 4).
+ * If lineLength <= 0, then the output will not be divided into lines (chunks). Ignored when
+ * decoding.
+ * @since 1.4
+ */
+ public Base64(int lineLength) {
+ this(lineLength, CHUNK_SEPARATOR);
+ }
+
+ /**
+ * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
+ * <p>
+ * When encoding the line length and line separator are given in the constructor, and the encoding table is
+ * STANDARD_ENCODE_TABLE.
+ * </p>
+ * <p>
+ * Line lengths that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data.
+ * </p>
+ * <p>
+ * When decoding all variants are supported.
+ * </p>
+ *
+ * @param lineLength Each line of encoded data will be at most of the given length (rounded down to nearest
+ * multiple of 4).
+ * If lineLength <= 0, then the output will not be divided into lines (chunks). Ignored when
+ * decoding.
+ * @param lineSeparator Each line of encoded data will end with this sequence of bytes.
+ * @throws IllegalArgumentException Thrown when the provided lineSeparator included some base64 characters.
+ * @since 1.4
+ */
+ public Base64(int lineLength, byte[] lineSeparator) {
+ this(lineLength, lineSeparator, false);
+ }
+
+ /**
+ * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
+ * <p>
+ * When encoding the line length and line separator are given in the constructor, and the encoding table is
+ * STANDARD_ENCODE_TABLE.
+ * </p>
+ * <p>
+ * Line lengths that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data.
+ * </p>
+ * <p>
+ * When decoding all variants are supported.
+ * </p>
+ *
+ * @param lineLength Each line of encoded data will be at most of the given length (rounded down to nearest
+ * multiple of 4).
+ * If lineLength <= 0, then the output will not be divided into lines (chunks). Ignored when
+ * decoding.
+ * @param lineSeparator Each line of encoded data will end with this sequence of bytes.
+ * @param urlSafe Instead of emitting '+' and '/' we emit '-' and '_' respectively. urlSafe is only applied
+ * to encode
+ * operations. Decoding seamlessly handles both modes.
+ * @throws IllegalArgumentException The provided lineSeparator included some base64 characters. That's not going to
+ * work!
+ * @since 1.4
+ */
+ public Base64(int lineLength, byte[] lineSeparator, boolean urlSafe) {
+ super(BYTES_PER_UNENCODED_BLOCK, BYTES_PER_ENCODED_BLOCK,
+ lineLength,
+ lineSeparator == null ? 0 : lineSeparator.length);
+ // TODO could be simplified if there is no requirement to reject invalid line sep when length <=0
+ // @see test case Base64Test.testConstructors()
+ if (lineSeparator != null) {
+ if (containsAlphabetOrPad(lineSeparator)) {
+ String sep = newStringUtf8(lineSeparator);
+ throw new IllegalArgumentException("lineSeparator must not contain base64 characters: [" + sep + "]");
+ }
+ if (lineLength > 0) { // null line-sep forces no chunking rather than throwing IAE
+ this.encodeSize = BYTES_PER_ENCODED_BLOCK + lineSeparator.length;
+ this.lineSeparator = new byte[lineSeparator.length];
+ System.arraycopy(lineSeparator, 0, this.lineSeparator, 0, lineSeparator.length);
+ } else {
+ this.encodeSize = BYTES_PER_ENCODED_BLOCK;
+ this.lineSeparator = null;
+ }
+ } else {
+ this.encodeSize = BYTES_PER_ENCODED_BLOCK;
+ this.lineSeparator = null;
+ }
+ this.decodeSize = this.encodeSize - 1;
+ this.encodeTable = urlSafe ? URL_SAFE_ENCODE_TABLE : STANDARD_ENCODE_TABLE;
+ }
+
+ /**
+ * <p>
+ * Encodes all of the provided data, starting at inPos, for inAvail bytes. Must be called at least twice: once with
+ * the data to encode, and once with inAvail set to "-1" to alert encoder that EOF has been reached, so flush last
+ * remaining bytes (if not multiple of 3).
+ * </p>
+ * <p>
+ * Thanks to "commons" project in ws.apache.org for the bitwise operations, and general approach.
+ * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
+ * </p>
+ *
+ * @param in byte[] array of binary data to base64 encode.
+ * @param inPos Position to start reading data from.
+ * @param inAvail Amount of bytes available from input for encoding.
+ */
+ @Override
+ void encode(byte[] in, int inPos, int inAvail) {
+ if (eof) {
+ return;
+ }
+ // inAvail < 0 is how we're informed of EOF in the underlying data we're
+ // encoding.
+ if (inAvail < 0) {
+ eof = true;
+ if (0 == modulus && lineLength == 0) {
+ return; // no leftovers to process and not using chunking
+ }
+ ensureBufferSize(encodeSize);
+ int savedPos = pos;
+ switch (modulus) { // 0-2
+ case 1: // 8 bits = 6 + 2
+ buffer[pos++] = encodeTable[(bitWorkArea >> 2) & MASK_6BITS]; // top 6 bits
+ buffer[pos++] = encodeTable[(bitWorkArea << 4) & MASK_6BITS]; // remaining 2
+ // URL-SAFE skips the padding to further reduce size.
+ if (encodeTable == STANDARD_ENCODE_TABLE) {
+ buffer[pos++] = PAD;
+ buffer[pos++] = PAD;
+ }
+ break;
+
+ case 2: // 16 bits = 6 + 6 + 4
+ buffer[pos++] = encodeTable[(bitWorkArea >> 10) & MASK_6BITS];
+ buffer[pos++] = encodeTable[(bitWorkArea >> 4) & MASK_6BITS];
+ buffer[pos++] = encodeTable[(bitWorkArea << 2) & MASK_6BITS];
+ // URL-SAFE skips the padding to further reduce size.
+ if (encodeTable == STANDARD_ENCODE_TABLE) {
+ buffer[pos++] = PAD;
+ }
+ break;
+ }
+ currentLinePos += pos - savedPos; // keep track of current line position
+ // if currentPos == 0 we are at the start of a line, so don't add CRLF
+ if (lineLength > 0 && currentLinePos > 0) {
+ System.arraycopy(lineSeparator, 0, buffer, pos, lineSeparator.length);
+ pos += lineSeparator.length;
+ }
+ } else {
+ for (int i = 0; i < inAvail; i++) {
+ ensureBufferSize(encodeSize);
+ modulus = (modulus + 1) % BYTES_PER_UNENCODED_BLOCK;
+ int b = in[inPos++];
+ if (b < 0) {
+ b += 256;
+ }
+ bitWorkArea = (bitWorkArea << 8) + b; // BITS_PER_BYTE
+ if (0 == modulus) { // 3 bytes = 24 bits = 4 * 6 bits to extract
+ buffer[pos++] = encodeTable[(bitWorkArea >> 18) & MASK_6BITS];
+ buffer[pos++] = encodeTable[(bitWorkArea >> 12) & MASK_6BITS];
+ buffer[pos++] = encodeTable[(bitWorkArea >> 6) & MASK_6BITS];
+ buffer[pos++] = encodeTable[bitWorkArea & MASK_6BITS];
+ currentLinePos += BYTES_PER_ENCODED_BLOCK;
+ if (lineLength > 0 && lineLength <= currentLinePos) {
+ System.arraycopy(lineSeparator, 0, buffer, pos, lineSeparator.length);
+ pos += lineSeparator.length;
+ currentLinePos = 0;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * <p>
+ * Decodes all of the provided data, starting at inPos, for inAvail bytes. Should be called at least twice: once
+ * with the data to decode, and once with inAvail set to "-1" to alert decoder that EOF has been reached. The "-1"
+ * call is not necessary when decoding, but it doesn't hurt, either.
+ * </p>
+ * <p>
+ * Ignores all non-base64 characters. This is how chunked (e.g. 76 character) data is handled, since CR and LF are
+ * silently ignored, but has implications for other bytes, too. This method subscribes to the garbage-in,
+ * garbage-out philosophy: it will not check the provided data for validity.
+ * </p>
+ * <p>
+ * Thanks to "commons" project in ws.apache.org for the bitwise operations, and general approach.
+ * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
+ * </p>
+ *
+ * @param in byte[] array of ascii data to base64 decode.
+ * @param inPos Position to start reading data from.
+ * @param inAvail Amount of bytes available from input for encoding.
+ */
+ @Override
+ void decode(byte[] in, int inPos, int inAvail) {
+ if (eof) {
+ return;
+ }
+ if (inAvail < 0) {
+ eof = true;
+ }
+ for (int i = 0; i < inAvail; i++) {
+ ensureBufferSize(decodeSize);
+ byte b = in[inPos++];
+ if (b == PAD) {
+ // We're done.
+ eof = true;
+ break;
+ } else {
+ if (b >= 0 && b < DECODE_TABLE.length) {
+ int result = DECODE_TABLE[b];
+ if (result >= 0) {
+ modulus = (modulus + 1) % BYTES_PER_ENCODED_BLOCK;
+ bitWorkArea = (bitWorkArea << BITS_PER_ENCODED_BYTE) + result;
+ if (modulus == 0) {
+ buffer[pos++] = (byte) ((bitWorkArea >> 16) & MASK_8BITS);
+ buffer[pos++] = (byte) ((bitWorkArea >> 8) & MASK_8BITS);
+ buffer[pos++] = (byte) (bitWorkArea & MASK_8BITS);
+ }
+ }
+ }
+ }
+ }
+
+ // Two forms of EOF as far as base64 decoder is concerned: actual
+ // EOF (-1) and first time '=' character is encountered in stream.
+ // This approach makes the '=' padding characters completely optional.
+ if (eof && modulus != 0) {
+ ensureBufferSize(decodeSize);
+
+ // We have some spare bits remaining
+ // Output all whole multiples of 8 bits and ignore the rest
+ switch (modulus) {
+ // case 1: // 6 bits - ignore entirely
+ // break;
+ case 2: // 12 bits = 8 + 4
+ bitWorkArea = bitWorkArea >> 4; // dump the extra 4 bits
+ buffer[pos++] = (byte) ((bitWorkArea) & MASK_8BITS);
+ break;
+ case 3: // 18 bits = 8 + 8 + 2
+ bitWorkArea = bitWorkArea >> 2; // dump 2 bits
+ buffer[pos++] = (byte) ((bitWorkArea >> 8) & MASK_8BITS);
+ buffer[pos++] = (byte) ((bitWorkArea) & MASK_8BITS);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Returns whether or not the <code>octet</code> is in the base 64 alphabet.
+ *
+ * @param octet The value to test
+ * @return <code>true</code> if the value is defined in the the base 64 alphabet, <code>false</code> otherwise.
+ * @since 1.4
+ */
+ public static boolean isBase64(byte octet) {
+ return octet == PAD_DEFAULT || (octet >= 0 && octet < DECODE_TABLE.length && DECODE_TABLE[octet] != -1);
+ }
+
+ /**
+ * Tests a given String to see if it contains only valid characters within the Base64 alphabet. Currently the
+ * method treats whitespace as valid.
+ *
+ * @param base64 String to test
+ * @return <code>true</code> if all characters in the String are valid characters in the Base64 alphabet or if
+ * the String is empty; <code>false</code>, otherwise
+ * @since 1.5
+ */
+ public static boolean isBase64(String base64) {
+ return isBase64(getBytesUtf8(base64));
+ }
+
+ /**
+ * Tests a given byte array to see if it contains only valid characters within the Base64 alphabet. Currently the
+ * method treats whitespace as valid.
+ *
+ * @param arrayOctet byte array to test
+ * @return <code>true</code> if all bytes are valid characters in the Base64 alphabet or if the byte array is empty;
+ * <code>false</code>, otherwise
+ * @since 1.5
+ */
+ public static boolean isBase64(byte[] arrayOctet) {
+ for (int i = 0; i < arrayOctet.length; i++) {
+ if (!isBase64(arrayOctet[i]) && !isWhiteSpace(arrayOctet[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Encodes binary data using the base64 algorithm but does not chunk the output.
+ * <p/>
+ * NOTE: We changed the behaviour of this method from multi-line chunking (commons-codec-1.4) to
+ * single-line non-chunking (commons-codec-1.5).
+ *
+ * @param binaryData binary data to encode
+ * @return String containing Base64 characters.
+ * @since 1.4 (NOTE: 1.4 chunked the output, whereas 1.5 does not).
+ */
+ public static String encodeBase64String(byte[] binaryData) {
+ return newStringUtf8(encodeBase64(binaryData, false));
+ }
+
+ /**
+ * Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks.
+ *
+ * @param binaryData Array containing binary data to encode.
+ * @param isChunked if <code>true</code> this encoder will chunk the base64 output into 76 character blocks
+ * @return Base64-encoded data.
+ * @throws IllegalArgumentException Thrown when the input array needs an output array bigger than {@link
+ * Integer#MAX_VALUE}
+ */
+ public static byte[] encodeBase64(byte[] binaryData, boolean isChunked) {
+ return encodeBase64(binaryData, isChunked, false);
+ }
+
+ /**
+ * Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks.
+ *
+ * @param binaryData Array containing binary data to encode.
+ * @param isChunked if <code>true</code> this encoder will chunk the base64 output into 76 character blocks
+ * @param urlSafe if <code>true</code> this encoder will emit - and _ instead of the usual + and / characters.
+ * @return Base64-encoded data.
+ * @throws IllegalArgumentException Thrown when the input array needs an output array bigger than {@link
+ * Integer#MAX_VALUE}
+ * @since 1.4
+ */
+ public static byte[] encodeBase64(byte[] binaryData, boolean isChunked, boolean urlSafe) {
+ return encodeBase64(binaryData, isChunked, urlSafe, Integer.MAX_VALUE);
+ }
+
+ /**
+ * Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks.
+ *
+ * @param binaryData Array containing binary data to encode.
+ * @param isChunked if <code>true</code> this encoder will chunk the base64 output into 76 character blocks
+ * @param urlSafe if <code>true</code> this encoder will emit - and _ instead of the usual + and / characters.
+ * @param maxResultSize The maximum result size to accept.
+ * @return Base64-encoded data.
+ * @throws IllegalArgumentException Thrown when the input array needs an output array bigger than maxResultSize
+ * @since 1.4
+ */
+ public static byte[] encodeBase64(byte[] binaryData, boolean isChunked, boolean urlSafe, int maxResultSize) {
+ if (binaryData == null || binaryData.length == 0) {
+ return binaryData;
+ }
+
+ // Create this so can use the super-class method
+ // Also ensures that the same roundings are performed by the ctor and the code
+ Base64 b64 = isChunked ? new Base64(urlSafe) : new Base64(0, CHUNK_SEPARATOR, urlSafe);
+ long len = b64.getEncodedLength(binaryData);
+ if (len > maxResultSize) {
+ throw new IllegalArgumentException("Input array too big, the output array would be bigger (" +
+ len +
+ ") than the specified maximum size of " +
+ maxResultSize);
+ }
+
+ return b64.encode(binaryData);
+ }
+
+ /**
+ * Decodes a Base64 String into octets
+ *
+ * @param base64String String containing Base64 data
+ * @return Array containing decoded data.
+ * @since 1.4
+ */
+ public static byte[] decodeBase64(String base64String) {
+ return new Base64().decode(base64String);
+ }
+
+ /**
+ * Returns whether or not the <code>octet</code> is in the Base32 alphabet.
+ *
+ * @param octet The value to test
+ * @return <code>true</code> if the value is defined in the the Base32 alphabet <code>false</code> otherwise.
+ */
+ @Override
+ protected boolean isInAlphabet(byte octet) {
+ return octet >= 0 && octet < decodeTable.length && decodeTable[octet] != -1;
+ }
+
+}